Estimate effective population size (Ne) of PWS from allele frequncy chagnes

source("../Rscripts/BaseScripts.R")
require(data.table)
require(plyr)
require(RColorBrewer)
library(poolSeq)

Nest/PoolSeq package is used.

Ref: doi: 10.1534/genetics.116.191197

  1. Subset VCF files by population
#subset a VCF file by population (subset_vcf_byPopPWS.sh)

#!/bin/bash
#SBATCH --job-name=subsetPop
#SBATCH --mem=16G 
#SBATCH --nodes=4 
#SBATCH --ntasks=8 
#SBATCH -e subsetPop.err  
#SBATCH --time=72:00:00  
#SBATCH --mail-user=ktist@ucdavis.edu ##email you when job starts,ends,etc
#SBATCH --mail-type=ALL

#SBATCH -p high  

module load bcftools

bcftools view -Oz -S /home/ktist/ph/data/new_vcf/MD7000/population/PWS07.txt --threads 16 /home/ktist/ph/data/new_vcf/MD7000/PWSonly_NS0.5_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly07_maf05.vcf.gz 
bcftools view -Oz -S /home/ktist/ph/data/new_vcf/MD7000/population/PWS17.txt --threads 16 /home/ktist/ph/data/new_vcf/MD7000/PWSonly_NS0.5_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly17_maf05.vcf.gz 
bcftools view -Oz -S /home/ktist/ph/data/new_vcf/MD7000/population/PWS91.txt --threads 16 /home/ktist/ph/data/new_vcf/MD7000/PWSonly_NS0.5_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly91_maf05.vcf.gz 
bcftools view -Oz -S /home/ktist/ph/data/new_vcf/MD7000/population/PWS96.txt --threads 16 /home/ktist/ph/data/new_vcf/MD7000/PWSonly_NS0.5_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly96_maf05.vcf.gz 
  1. Calculate allele frequency using VCFtools
#Calculate allele frequency using VCFtools (calculateAF_VCFtools.sh)

#!/bin/bash -l
#SBATCH --job-name=calculateAF
#SBATCH --mem=16G
#SBATCH --nodes=4 
#SBATCH --ntasks=8 
#SBATCH --error calculateAF.err
#SBATCH --time=48:00:00
#SBATCH --mail-user=ktist@ucdavis.edu ##email you when job starts,ends,etc
#SBATCH --mail-type=ALL
#SBATCH -p high 

module load vcftools

vcftools --gzvcf /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly07_maf05.vcf.gz --freq --out /home/ktist/ph/data/new_vcf/MD7000/AF/PWSonly07_maf05_freq 
vcftools --gzvcf /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly17_maf05.vcf.gz --freq --out /home/ktist/ph/data/new_vcf/MD7000/AF/PWSonly17_maf05_freq 
vcftools --gzvcf /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly91_maf05.vcf.gz --freq --out /home/ktist/ph/data/new_vcf/MD7000/AF/PWSonly91_maf05_freq 
vcftools --gzvcf /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly96_maf05.vcf.gz --freq --out /home/ktist/ph/data/new_vcf/MD7000/AF/PWSonly96_maf05_freq 
  1. Obtain read depths from VCF files
#Obtain depth information from VCF files (extract_coveragePWS.sh)

#!/bin/bash
#SBATCH --job-name=extract_coverage 
#SBATCH --mem=16G 
#SBATCH --ntasks=1 
#SBATCH -e extract_coverage.err  
#SBATCH --time=48:00:00  
#SBATCH --mail-user=ktist@ucdavis.edu ##email you when job starts,ends,etc
#SBATCH --mail-type=ALL
#SBATCH -p high  

module load bcftools
bcftools query -f '%CHROM  %POS  %INFO/DP\n' /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly07_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/depth/PWSonly07_maf05.depth.info 
bcftools query -f '%CHROM  %POS  %INFO/DP\n' /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly17_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/depth/PWSonly17_maf05.depth.info 
bcftools query -f '%CHROM  %POS  %INFO/DP\n' /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly91_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/depth/PWSonly91_maf05.depth.info 
bcftools query -f '%CHROM  %POS  %INFO/DP\n' /home/ktist/ph/data/new_vcf/MD7000/population/PWSonly96_maf05.vcf.gz > /home/ktist/ph/data/new_vcf/MD7000/depth/PWSonly96_maf05.depth.info 

Use poolSeq to calcualte Ne

1. Read AF (frq) files and filter out extreme values and uninformative loci

source("../Rscripts/BaseScripts.R")
library(poolSeq)

pops<-c("PWS91","PWS96","PWS07","PWS17")
yr<-c(91,96,"07",17)
#Read the allele freq data for PWS

for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/AF/PWSonly",yr[i],"_maf05_freq.frq"),stringsAsFactors = FALSE,header = FALSE, skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    df$maf<-substr(df$MAF, 3,10)
    df<-df[,c(1,2,7)]
    df$maf<-as.numeric(df$maf)
    assign(paste0("pws",i),df)
}

#combine AF for all years
pws<-cbind(pws1, pws2[,3],pws3[,3],pws4[,3])
colnames(pws)<-c("chr","pos","F0","F1","F2","F3")
write.csv(pws, "../Output/Ne/PWSonly_AF.csv")

#Read depth information
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/depth/PWSonly",yr[i],"_maf05.depth.info"), header=F)
    colnames(df)<-c("chr","pos","depth")
    assign(paste0("D",i),df)
}
#combine Depth for all years
DP<-cbind(D1, D2[,3],D3[,3],D4[,3])
colnames(DP)<-c("chr","pos","F0","F1","F2","F3")
write.csv(DP,"../Output/Ne/PWSonly_read_depth.csv")

#Find SNPs with extreme values and uninformative loci and remove them
retain<-checkSNP(pws[,"F0"],pws[,"F3"],DP[,"F0"], DP[,"F3"])
length(retain[retain==F]) #65317 will be removed

#filtered the snp dataset
pws_filtered<-pws[retain,]
DP_filtered<-DP[retain,]

#Look at F0 and F1
retain1<-checkSNP(pws_filtered[,"F0"],pws_filtered[,"F1"],DP_filtered[,"F0"], DP_filtered[,"F1"])
length(retain1[retain1==F]) #0

retain2<-checkSNP(pws_filtered[,"F0"],pws_filtered[,"F2"],DP_filtered[,"F0"], DP_filtered[,"F2"])
length(retain2[retain2==F]) #0

retain3<-checkSNP(pws_filtered[,"F1"],pws_filtered[,"F2"],DP_filtered[,"F1"], DP_filtered[,"F2"])
length(retain3[retain3==F]) #22479

retain4<-checkSNP(pws_filtered[,"F2"],pws_filtered[,"F3"],DP_filtered[,"F2"], DP_filtered[,"F3"])
length(retain4[retain4==F]) #34809

2. Run poolSeq to obtain short-term Ne values

PWS between 1991 and 2017

methods<-c("W.planI","W.planII","JR.planI","JR.planII","P.planI","P.planII","P.alt.1step.planII")

#calcualte Ne for PWS91-PWS17 period 
pws_Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    pws_Ne$Ne[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                  method=methods[i], Ncensus=1000,poolSize=c(58,56))
    pws_Ne$Ne_10000[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                                   method=methods[i], Ncensus=100000,poolSize=c(58,56))
    
}
write.csv(pws_Ne,"../Output/Ne/Ne_estimation_PWSonly91-17_vcfAF.csv")
#PlanI requires Ncensus, PlanII does not require Ncensus
pws_Ne<-read.csv("../Output/Ne/Ne_estimation_PWSonly91-17_vcfAF.csv", row.names = 1)
library(knitr)
kable(pws_Ne, caption = "Estiamted Ne")

PlanI requires ‘Ncensus’,and PlanII does not require Ncensus. Ncensus =1000 [Ne] and 10000 Ne_10000. Does not make much difference after 10000

3. Estimate Ne for each time point

#further filtered the snp dataset
pws_filtered<-pws_filtered[retain3,]
DP_filtered<-DP_filtered[retain3,]
retain4<-checkSNP(pws_filtered[,"F2"],pws_filtered[,"F3"],DP_filtered[,"F2"], DP_filtered[,"F3"])
length(retain4[retain4==F])
pws_filtered<-pws_filtered[retain4,]
DP_filtered<-DP_filtered[retain4,]


Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    Ne$Ne01_t1[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F1"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F1"], t=1, 
                         method=methods[i], Ncensus=10000,poolSize=c(58,72))
    Ne$Ne12_t2[i]<-estimateNe(p0=pws_filtered[,"F1"], pt=pws_filtered[,"F2"], cov0=DP_filtered[,"F1"], covt=DP_filtered[,"F2"], t=1.8, 
                              method=methods[i], Ncensus=10000,poolSize=c(72,46))
    Ne$Ne23_t2[i]<-estimateNe(p0=pws_filtered[,"F2"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F2"], covt=DP_filtered[,"F3"], t=1.7, 
                              method=methods[i], Ncensus=10000,poolSize=c(46,56))
}

write.csv(Ne, "../Output/Ne/Ne_estimation_PWSonly_eachTimePeriod_vcfAF.csv")
Ne

4. Plot the results

colnames(Ne)[2:4]<-c("T1","T2","T3")
nem<-reshape2::melt(Ne, id.vars="methods",value.name ="Ne")

ggplot(nem, aes(x=variable, y=Ne, color=methods))+
    geom_point()+
    theme_classic()+ylab("Ne")+xlab("Time period")+
    geom_path(aes(x=variable, y=Ne, group=methods,color=methods))+
    theme(legend.title=element_blank())+ggtitle("PWS")
ggsave("../Output/Ne/Ne_estimates_overtime_PWS.png", width = 6, height = 4, dpi=150)

  • Compare the results with PWSonly_maf0.05 vs. PWS_maf0.05
pops<-c("PWS91","PWS96","PWS07","PWS17")
yr<-c(91,96,"07",17)
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/AF/PWS",yr[i],"_maf05_af.frq"),stringsAsFactors = FALSE,header = FALSE, skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    df$maf<-substr(df$MAF, 3,10)
    df<-df[,c(1,2,7)]
    df$maf<-as.numeric(df$maf)
    assign(paste0("pws",i),df)
}

#combine AF for all years
pws<-cbind(pws1, pws2[,3],pws3[,3],pws4[,3])
colnames(pws)<-c("chr","pos","F0","F1","F2","F3")
write.csv(pws, "../Output/Ne/PWS_AF.csv")

#Read depth information
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/depth/PWS",yr[i],"_maf05.depth.info"), header=F)
    colnames(df)<-c("chr","pos","depth")
    assign(paste0("D",i),df)
}
#combine Depth for all years
DP<-cbind(D1, D2[,3],D3[,3],D4[,3])
colnames(DP)<-c("chr","pos","F0","F1","F2","F3")
#write.csv(DP,"../Output/Ne/PWS_read_depth.csv")

#Find SNPs with extreme values and uninformative loci and remove them
retain<-checkSNP(pws[,"F0"],pws[,"F3"],DP[,"F0"], DP[,"F3"])
length(retain[retain==F]) #65317 will be removed

#filtered the snp dataset
pws_filtered<-pws[retain,]
DP_filtered<-DP[retain,]

#Look at F0 and F1
retain1<-checkSNP(pws_filtered[,"F0"],pws_filtered[,"F1"],DP_filtered[,"F0"], DP_filtered[,"F1"])
length(retain1[retain1==F]) #0

retain2<-checkSNP(pws_filtered[,"F0"],pws_filtered[,"F2"],DP_filtered[,"F0"], DP_filtered[,"F2"])
length(retain2[retain2==F]) #0

retain3<-checkSNP(pws_filtered[,"F1"],pws_filtered[,"F2"],DP_filtered[,"F1"], DP_filtered[,"F2"])
length(retain3[retain3==F]) #5815

retain4<-checkSNP(pws_filtered[,"F2"],pws_filtered[,"F3"],DP_filtered[,"F2"], DP_filtered[,"F3"])
length(retain4[retain4==F]) #9857

methods<-c("W.planI","W.planII","JR.planI","JR.planII","P.planI","P.planII","P.alt.1step.planII")

#calcualte Ne for PWS91-PWS17 period 
pws_Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    pws_Ne$Ne[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                  method=methods[i], Ncensus=1000,poolSize=c(58,56))
    pws_Ne$Ne_10000[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                                   method=methods[i], Ncensus=100000,poolSize=c(58,56))
    
}
library(knitr)
pws_Ne<-
kable(pws_Ne, caption = "Estiamted Ne")
#further filtered the snp dataset
pws_filtered<-pws_filtered[retain3,]
DP_filtered<-DP_filtered[retain3,]
retain4<-checkSNP(pws_filtered[,"F2"],pws_filtered[,"F3"],DP_filtered[,"F2"], DP_filtered[,"F3"])
pws_filtered<-pws_filtered[retain4,]
DP_filtered<-DP_filtered[retain4,]

Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    Ne$Ne01_t1[i]<-estimateNe(p0=pws_filtered[,"F0"], pt=pws_filtered[,"F1"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F1"], t=1, 
                         method=methods[i], Ncensus=10000,poolSize=c(58,72))
    Ne$Ne12_t2[i]<-estimateNe(p0=pws_filtered[,"F1"], pt=pws_filtered[,"F2"], cov0=DP_filtered[,"F1"], covt=DP_filtered[,"F2"], t=1.8, 
                              method=methods[i], Ncensus=10000,poolSize=c(72,46))
    Ne$Ne23_t2[i]<-estimateNe(p0=pws_filtered[,"F2"], pt=pws_filtered[,"F3"], cov0=DP_filtered[,"F2"], covt=DP_filtered[,"F3"], t=1.7, 
                              method=methods[i], Ncensus=10000,poolSize=c(46,56))
}
write.csv(Ne, "../Output/Ne/Ne_estimation_PWS_eachTimePeriod_vcfAF.csv")
Ne

colnames(Ne)[2:4]<-c("T1","T2","T3")
nem<-reshape2::melt(Ne, id.vars="methods",value.name ="Ne")

ggplot(nem, aes(x=variable, y=Ne, color=methods))+
    geom_point()+
    theme_classic()+ylab("Ne")+xlab("Time period")+
    geom_path(aes(x=variable, y=Ne, group=methods,color=methods))+
    theme(legend.title=element_blank())
ggsave("../Output/Ne/Ne_estimates_overtime_PWS_nonPWSonly.png", width = 6, height = 4, dpi=150)

  • Highly similar -can use PH_maf05 data

5. Calculate TB and SS Ne

    1. TB
size<-read.csv("../Data/popinfo/popsize.csv")
pops<-c("TB91","TB96","TB06","TB17")
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/AF/",pops[i],"_maf05_af.frq"),stringsAsFactors = FALSE,header = FALSE, skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    df$maf<-substr(df$MAF, 3,10)
    df<-df[,c(1,2,7)]
    df$maf<-as.numeric(df$maf)
    assign(paste0("AF",i),df)
}

#combine AF for all years
AF<-cbind(AF1, AF2[,3],AF3[,3],AF4[,3])
colnames(AF)<-c("chr","pos","F0","F1","F2","F3")
write.csv(AF, "../Output/Ne/TB_maf05_AF.csv")

#Read depth information
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/depth/",pops[i],"_maf05.depth.info"), header=F)
    colnames(df)<-c("chr","pos","depth")
    assign(paste0("D",i),df)
}
#combine Depth for all years
DP<-cbind(D1, D2[,3],D3[,3],D4[,3])
colnames(DP)<-c("chr","pos","F0","F1","F2","F3")
write.csv(DP,"../Output/Ne/TB_maf05_read_depth.csv")

#Find SNPs with extreme values and uninformative loci and remove them
retain<-checkSNP(AF[,"F0"],AF[,"F3"],DP[,"F0"], DP[,"F3"])
length(retain[retain==F]) #69743
AF_filtered<-AF[retain,]
DP_filtered<-DP[retain,]

#Look at F0 and F1
retain1<-checkSNP(AF_filtered[,"F0"],AF_filtered[,"F1"],DP_filtered[,"F0"], DP_filtered[,"F1"])
length(retain1[retain1==F]) #0

retain2<-checkSNP(AF_filtered[,"F0"],AF_filtered[,"F2"],DP_filtered[,"F0"], DP_filtered[,"F2"])
length(retain2[retain2==F]) #0

retain3<-checkSNP(AF_filtered[,"F1"],AF_filtered[,"F2"],DP_filtered[,"F1"], DP_filtered[,"F2"])
length(retain3[retain3==F]) #22479

retain4<-checkSNP(AF_filtered[,"F2"],AF_filtered[,"F3"],DP_filtered[,"F2"], DP_filtered[,"F3"])
length(retain[retain==F]) 

methods<-c("W.planI","W.planII","JR.planI","JR.planII","P.planI","P.planII","P.alt.1step.planII")

#calcualte Ne for 1991-2017 period 
AF_Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    AF_Ne$Ne[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                  method=methods[i], Ncensus=1000,poolSize=c(size$Freq[size$pop==pops[1]],size$Freq[size$pop==pops[4]] ))
    AF_Ne$Ne_10000[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F3"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F3"], t=5, 
                                   method=methods[i], Ncensus=100000,poolSize= c(size$Freq[size$pop==pops[1]], size$Freq[size$pop==pops[4]]))
    
}
write.csv(AF_Ne,"../Output/Ne/Ne_estimation_TB91-17_vcfAF.csv")

knitr::kable(AF_Ne, caption = "Estiamted Ne of TB")
# Estimate Ne for each time point  
AF_filtered<-AF_filtered[retain3,]
DP_filtered<-DP_filtered[retain3,]
AF_filtered<-AF_filtered[retain4,]
DP_filtered<-DP_filtered[retain4,]

Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    Ne$Ne01_t1[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F1"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F1"], t=1, 
                         method=methods[i], Ncensus=10000,poolSize=c(size$Freq[size$pop==pops[1]],size$Freq[size$pop==pops[2]]))
    Ne$Ne12_t2[i]<-estimateNe(p0=AF_filtered[,"F1"], pt=AF_filtered[,"F2"], cov0=DP_filtered[,"F1"], covt=DP_filtered[,"F2"], t=1.8, 
                              method=methods[i], Ncensus=10000,poolSize=c(size$Freq[size$pop==pops[2]],size$Freq[size$pop==pops[3]]))
    Ne$Ne23_t2[i]<-estimateNe(p0=AF_filtered[,"F2"], pt=AF_filtered[,"F3"], cov0=DP_filtered[,"F2"], covt=DP_filtered[,"F3"], t=1.7, 
                              method=methods[i], Ncensus=10000,poolSize=c(size$Freq[size$pop==pops[3]],size$Freq[size$pop==pops[4]]))
}

write.csv(Ne, "../Output/Ne/Ne_estimation_TB_eachTimePeriod_vcfAF.csv")

colnames(Ne)[2:4]<-c("T1","T2","T3")
nem<-reshape2::melt(Ne, id.vars="methods",value.name ="Ne")

ggplot(nem, aes(x=variable, y=Ne, color=methods))+
    geom_point()+
    theme_classic()+ylab("Ne")+xlab("Time period")+
    geom_path(aes(x=variable, y=Ne, group=methods,color=methods))+
    theme(legend.title=element_blank())+ggtitle("TB")
ggsave("../Output/Ne/Ne_estimates_overtime_TB.png", width = 6, height = 4, dpi=150)

    1. SS
pops<-c("SS96","SS06","SS17")
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/AF/",pops[i],"_maf05_af.frq"),stringsAsFactors = FALSE,header = FALSE, skip=1, col.names = c("chr","pos","n_allele","n_sample","MajorAF","MAF"))
    df$maf<-substr(df$MAF, 3,10)
    df<-df[,c(1,2,7)]
    df$maf<-as.numeric(df$maf)
    assign(paste0("AF",i),df)
}
#combine AF for all years
AF<-cbind(AF1, AF2[,3],AF3[,3])
colnames(AF)<-c("chr","pos","F0","F1","F2")
write.csv(AF, "../Output/Ne/SS_maf05_AF.csv")

#Read depth information
for (i in 1:length(pops)){
    df<-read.table(paste0("../Data/new_vcf/depth/",pops[i],"_maf05.depth.info"), header=F)
    colnames(df)<-c("chr","pos","depth")
    assign(paste0("D",i),df)
}
#combine Depth for all years
DP<-cbind(D1, D2[,3],D3[,3])
colnames(DP)<-c("chr","pos","F0","F1","F2")
write.csv(DP,"../Output/Ne/SS_maf05_read_depth.csv")

#Find SNPs with extreme values and uninformative loci and remove them
retain<-checkSNP(AF[,"F0"],AF[,"F2"],DP[,"F0"], DP[,"F2"])
length(retain[retain==F]) #10509
AF_filtered<-AF[retain,]
DP_filtered<-DP[retain,]

#Look at F0 and F1
retain1<-checkSNP(AF_filtered[,"F0"],AF_filtered[,"F1"],DP_filtered[,"F0"], DP_filtered[,"F1"])
length(retain1[retain1==F]) #0

retain2<-checkSNP(AF_filtered[,"F0"],AF_filtered[,"F2"],DP_filtered[,"F0"], DP_filtered[,"F2"])
length(retain2[retain2==F]) #0

retain3<-checkSNP(AF_filtered[,"F1"],AF_filtered[,"F2"],DP_filtered[,"F1"], DP_filtered[,"F2"])
length(retain3[retain3==F]) #26551

methods<-c("W.planI","W.planII","JR.planI","JR.planII","P.planI","P.planII","P.alt.1step.planII")
#calcualte Ne for 1991-2017 period 
AF_Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    AF_Ne$Ne[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F2"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F2"], t=5, 
                  method=methods[i], Ncensus=1000,poolSize=c(size$Freq[size$pop==pops[1]],size$Freq[size$pop==pops[3]]))
    AF_Ne$Ne_10000[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F2"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F2"], t=5, 
                                   method=methods[i], Ncensus=100000,poolSize= c(size$Freq[size$pop==pops[1]],size$Freq[size$pop==pops[3]]))
    
}
write.csv(AF_Ne,"../Output/Ne/Ne_estimation_SS96-17_vcfAF.csv")

knitr::kable(AF_Ne, caption = "Estiamted Ne of SS")
# Estimate Ne for each time point  
AF_filtered<-AF_filtered[retain3,]
DP_filtered<-DP_filtered[retain3,]
Ne<-data.frame(methods=methods)
for (i in 1: length(methods)){
    Ne$Ne01_t1[i]<-estimateNe(p0=AF_filtered[,"F0"], pt=AF_filtered[,"F1"], cov0=DP_filtered[,"F0"], covt=DP_filtered[,"F1"], t=1, 
                         method=methods[i], Ncensus=10000,poolSize=c(size$Freq[size$pop==pops[1]],size$Freq[size$pop==pops[2]]))
    Ne$Ne12_t2[i]<-estimateNe(p0=AF_filtered[,"F1"], pt=AF_filtered[,"F2"], cov0=DP_filtered[,"F1"], covt=DP_filtered[,"F2"], t=1.8, 
                              method=methods[i], Ncensus=10000,poolSize=c(size$Freq[size$pop==pops[2]],size$Freq[size$pop==pops[3]]))
}

write.csv(Ne, "../Output/Ne/Ne_estimation_SS_eachTimePeriod_vcfAF.csv")

colnames(Ne)[2:3]<-c("T1","T2")
nem<-reshape2::melt(Ne, id.vars="methods",value.name ="Ne")

ggplot(nem, aes(x=variable, y=Ne, color=methods))+
    geom_point()+
    theme_classic()+ylab("Ne")+xlab("Time period")+
    geom_path(aes(x=variable, y=Ne, group=methods,color=methods))+
    theme(legend.title=element_blank())+ggtitle("SS")
ggsave("../Output/Ne/Ne_estimates_overtime_SS.png", width = 6, height = 4, dpi=150)

Plot together the P.PlanII results

#Plot together (results from maf0.05 freq files)
library(tibble)
pops<-c("PWS","TB","SS")
Ne<-data.frame()
for (i in 1: length(pops)){
    df<-read.csv(paste0("../Output/Ne/Ne_estimation_",pops[i],"_eachTimePeriod_vcfAF.csv"), row.names = 1)
    df$pop<-pops[i]  
    if (i==3) {
        colnames(df)[2:3]<-c("T2","T3")
        df<-add_column(df, T1=NA, .after=1)
    }
    if (i!=3) colnames(df)[2:4]<-c("T1","T2","T3")
        
    Ne<-rbind(Ne, df[df$methods=="P.planII",])
}

Nem<-reshape2::melt(Ne[,2:5], id.vars="pop")

Nem$pop<-factor(Nem$pop, levels=c("TB","PWS","SS"))
ggplot(Nem, aes(x=variable, y=value, color=pop))+
    geom_point(size=2)+
    theme_classic()+ylab("Ne")+xlab("Time period")+
    geom_path(aes(x=variable, y=value, group=pop,color=pop))+
    theme(legend.title=element_blank())+
    scale_color_manual(values=cols)
ggsave("../Output/Ne/Ne_estimates_overtime_3pops.png", width = 6, height = 4, dpi=150)

Use the Jorde-Ryman temporal method from NeEstimator 2.1.

From https://github.com/pinskylab/codEvol calcNe_ANGSD.r

require(data.table)
require(boot)
source("../Rscripts/calcNe.R")

1. Read the mafs data from ANGSD & trim positions to unlinked loci

Starting with PWS pop

#MAF data
dat91<-fread("../Data/new_vcf/AF/PWS91.mafs.gz")
dat96<-fread("../Data/new_vcf/AF/PWS96.mafs.gz")
dat07<-fread("../Data/new_vcf/AF/PWS07.mafs.gz")
dat17<-fread("../Data/new_vcf/AF/PWS17.mafs.gz")
setkey(dat91, chromo, position)
setkey(dat96, chromo, position)
setkey(dat07, chromo, position)
setkey(dat17, chromo, position)

# unlinked loci from plink
unlnk<-fread('../Data/plink/prune/prune_50.5.0.5.prune.in')
setnames(unlnk, c("chromo","position"))

dat91<-merge(dat91, unlnk)
dat96<-merge(dat96, unlnk)
dat07<-merge(dat07, unlnk)
dat17<-merge(dat17, unlnk)

2. Combine two time points (calculate ΔAF), trim loci with freq > 0.1, and estiamte Ne

years<-c("91","96","07","17")
comb<-t(combn(years, 2))

estNe<-data.frame(pop1=comb[,1], pop2=comb[,2])

#Generation time (G) = 2.35 and 3.5
years<-c(1991,1996,2006,2017)
yr_comb<-data.frame(t(combn(years, 2)))
yrs<-yr_comb$X2-yr_comb$X1
gens1<-yrs/2.35
gens2<-yrs/3

for (i in 2: nrow(comb)){
    df1<-get(paste0("dat",comb[i,1]))
    df2<-get(paste0("dat",comb[i,2]))
    
    setnames(df1, c("knownEM", 'nInd'), c("freq1", 'nInd1'))
    setnames(df2, c("knownEM", 'nInd'), c("freq2", 'nInd2'))
    
    df <- df1[df2, .(chromo, position, freq1, freq2, nInd1, nInd2)][!is.na(freq1) & !is.na(freq2) & freq1 > 0.1 & freq2 > 0.1, ]
    g1=gens1[i]
    g2=gens2[i]
    
    estNe$Ne1[i]<-df[, jrNe2(freq1, freq2, nInd1, nInd2, g1)] 
    estNe$Ne2[i]<-df[, jrNe2(freq1, freq2, nInd1, nInd2, g2)] 
    
    # block bootstrapping across LGs
    uq.ch <- df[, sort(unique(chromo))]

    boot.re1 <- boot(uq.ch, jrNe2block, 1000, gen = g1, alldata = df)
    boot.re2 <- boot(uq.ch, jrNe2block, 1000, gen = g2, alldata = df)
    
    estNe$median1[i]<-median(boot.re1$t[is.finite(boot.re1$t)]) # median bootstrap
    estNe$median2[i]<-median(boot.re2$t[is.finite(boot.re2$t)]) # median bootstrap
    
    estNe$mean1[i]<-mean(boot.re1$t[is.finite(boot.re1$t)])
    estNe$mean2[i]<-mean(boot.re2$t[is.finite(boot.re2$t)])
    
    ci1<-boot.ci(boot.re1, type = c('perc'))
    ci2<-boot.ci(boot.re2, type = c('perc'))
    
    #95% C.I.
    estNe$CI.low1[i]<-ci1$percent[4]
    estNe$CI.up1[i]<-ci1$percent[5]
    
    estNe$CI.low2[i]<-ci2$percent[4]
    estNe$CI.up2[i]<-ci2$percent[5]
    
    
    #reset the attibutes
    setnames(df1, c("freq1", 'nInd1'),c("knownEM", 'nInd'))
    setnames(df2, c("freq2", 'nInd2'),c("knownEM", 'nInd'))
}

write.csv(estNe,"../Output/Ne/Jorde-Ryman_Ne.estimates_PWS_G3.csv")

#estNe<-read.csv("../Output/Ne/Jorde-Ryman_Ne.estimates_PWS_G.csv", row.names = 1)
estNe$year<-apply(estNe["pop2"],1, function(x) {if (x=="96") x=1996
                   else if (x=="07") x=2007
                   else if (x=="17") x=2017})
#G=2.35 (Ne1)
ggplot(estNe[c(1,4,6),], aes(x=year, y=Ne1))+
    geom_point(size=2, color="blue")+
    geom_errorbar(aes(ymin = CI.low1, ymax = CI.up1), width = 0.2, color="blue")+
    geom_path(color="blue")+ylab("Estiamted Ne")+xlab("Year")+
    theme_classic()+ggtitle("PWS")
ggsave("../Output/Ne/Jorde-Ryman_Ne.estimates_PWS_G2.35.png", width = 5, height = 3, dpi=300)

ggplot(estNe[c(1,4,6),], aes(x=year, y=Ne2))+
    geom_point(size=2, color="blue")+
    geom_errorbar(aes(ymin = CI.low2, ymax = CI.up2), width = 0.2, color="blue")+
    geom_path(color="blue")+ylab("Estiamted Ne")+xlab("Year")+
    theme_classic()+ggtitle("PWS")
ggsave("../Output/Ne/Jorde-Ryman_Ne.estimates_PWS_G3.png", width = 5, height = 3, dpi=300)
knitr::kable(estNe)

  • TB pop
#MAF data
dat91<-fread("../Data/new_vcf/AF/TB91.mafs.gz")
dat96<-fread("../Data/new_vcf/AF/TB96.mafs.gz")
dat06<-fread("../Data/new_vcf/AF/TB06.mafs.gz")
dat17<-fread("../Data/new_vcf/AF/TB17.mafs.gz")
setkey(dat91, chromo, position)
setkey(dat96, chromo, position)
setkey(dat06, chromo, position)
setkey(dat17, chromo, position)

# unlinked loci from plink
unlnk<-fread('../Data/plink/prune/prune_50.5.0.5.prune.in')
setnames(unlnk, c("chromo","position"))

dat91<-merge(dat91, unlnk)
dat96<-merge(dat96, unlnk)
dat06<-merge(dat06, unlnk)
dat17<-merge(dat17, unlnk)

years<-c("91","96","06","17")
comb<-t(combn(years, 2))
estNe<-data.frame(pop1=comb[,1], pop2=comb[,2])

years<-c(1991,1996,2006,2017)
yr_comb<-data.frame(t(combn(years, 2)))
yrs<-yr_comb$X2-yr_comb$X1
#gens1<-yrs/2.35
gens<-yrs/3

for (i in 1: nrow(comb)){
    df1<-get(paste0("dat",comb[i,1]))
    df2<-get(paste0("dat",comb[i,2]))
    
    setnames(df1, c("knownEM", 'nInd'), c("freq1", 'nInd1'))
    setnames(df2, c("knownEM", 'nInd'), c("freq2", 'nInd2'))
    
    df <- df1[df2, .(chromo, position, freq1, freq2, nInd1, nInd2)][!is.na(freq1) & !is.na(freq2) & freq1 > 0.1 & freq2 > 0.1, ]
    g=gens[i]
    
    estNe$Ne[i]<-df[, jrNe2(freq1, freq2, nInd1, nInd2, g)] 

    # block bootstrapping across LGs
    uq.ch <- df[, sort(unique(chromo))]

    boot.re <- boot(uq.ch, jrNe2block, 1000, gen = g, alldata = df)
    estNe$median[i]<-median(boot.re$t[is.finite(boot.re$t)]) # median bootstrap
    estNe$mean[i]<-mean(boot.re$t[is.finite(boot.re$t)])
    ci<-boot.ci(boot.re, type = c('perc'))
    #95% C.I.
    estNe$CI.low[i]<-ci$percent[4]
    estNe$CI.up[i]<-ci$percent[5]
    
    #reset the attibutes
    setnames(df1, c("freq1", 'nInd1'),c("knownEM", 'nInd'))
    setnames(df2, c("freq2", 'nInd2'),c("knownEM", 'nInd'))
}

write.csv(estNe,"../Output/Ne/Jorde-Ryman_Ne.estimates_TB_G3.csv")

#estNe<-read.csv("../Output/Ne/Jorde-Ryman_Ne.estimates_TB_G3.csv", row.names = 1)
estNe$year<-apply(estNe["pop2"],1, function(x) {if (x=="96") x=1996
                   else if (x=="06") x=2006
                   else if (x=="17") x=2017})

ggplot(estNe[c(1,4,6),], aes(x=year, y=Ne))+
    geom_point(size=2, color="blue")+
    geom_errorbar(aes(ymin = CI.low, ymax = CI.up), width = 0.2, color="blue")+
    geom_path(color="blue")+ylab("Estiamted Ne")+xlab("Year")+
    theme_classic()+ggtitle("TB")
ggsave("../Output/Ne/Jorde-Ryman_Ne.estimates_TB_G3.png", width = 5, height = 3, dpi=300)

  • SS population
#MAF data
dat96<-fread("../Data/new_vcf/AF/SS96.mafs.gz")
dat06<-fread("../Data/new_vcf/AF/SS06.mafs.gz")
dat17<-fread("../Data/new_vcf/AF/SS17.mafs.gz")
setkey(dat96, chromo, position)
setkey(dat06, chromo, position)
setkey(dat17, chromo, position)

# unlinked loci from plink
unlnk<-fread('../Data/plink/prune/prune_50.5.0.5.prune.in')
setnames(unlnk, c("chromo","position"))

dat96<-merge(dat96, unlnk)
dat06<-merge(dat06, unlnk)
dat17<-merge(dat17, unlnk)

years<-c("96","06","17")
comb<-t(combn(years, 2))
estNe<-data.frame(pop1=comb[,1], pop2=comb[,2])

years<-c(1996,2006,2017)
yr_comb<-data.frame(t(combn(years, 2)))
yrs<-yr_comb$X2-yr_comb$X1
gens<-yrs/3

for (i in 1: nrow(comb)){
    df1<-get(paste0("dat",comb[i,1]))
    df2<-get(paste0("dat",comb[i,2]))
    
    setnames(df1, c("knownEM", 'nInd'), c("freq1", 'nInd1'))
    setnames(df2, c("knownEM", 'nInd'), c("freq2", 'nInd2'))
    
    df <- df1[df2, .(chromo, position, freq1, freq2, nInd1, nInd2)][!is.na(freq1) & !is.na(freq2) & freq1 > 0.1 & freq2 > 0.1, ]
    g=gens[i]
    
    estNe$Ne[i]<-df[, jrNe2(freq1, freq2, nInd1, nInd2, g)] 

    # block bootstrapping across LGs
    uq.ch <- df[, sort(unique(chromo))]

    boot.re <- boot(uq.ch, jrNe2block, 1000, gen = g, alldata = df)
    estNe$median[i]<-median(boot.re$t[is.finite(boot.re$t)]) # median bootstrap
    estNe$mean[i]<-mean(boot.re$t[is.finite(boot.re$t)])
    ci<-boot.ci(boot.re, type = c('perc'))
    #95% C.I.
    estNe$CI.low[i]<-ci$percent[4]
    estNe$CI.up[i]<-ci$percent[5]
    
    #reset the attibutes
    setnames(df1, c("freq1", 'nInd1'),c("knownEM", 'nInd'))
    setnames(df2, c("freq2", 'nInd2'),c("knownEM", 'nInd'))
}

write.csv(estNe,"../Output/Ne/Jorde-Ryman_Ne.estimates_SS_G3.csv")

#estNe<-read.csv("../Output/Ne/Jorde-Ryman_Ne.estimates_SS_G3.csv", row.names = 1)
estNe$year<-apply(estNe["pop2"],1, function(x) {if (x=="96") x=1996
                   else if (x=="06") x=2006
                   else if (x=="17") x=2017})

ggplot(estNe[c(1,3),], aes(x=year, y=Ne))+
    geom_point(size=2, color="blue")+
    geom_errorbar(aes(ymin = CI.low, ymax = CI.up), width = 0.2, color="blue")+
    geom_path(color="blue")+ylab("Estiamted Ne")+xlab("Year")+
    theme_classic()+ggtitle("SS")
ggsave("../Output/Ne/Jorde-Ryman_Ne.estimates_SS_G3.png", width = 5, height = 3, dpi=300)

  • Plot 3 populations together
ne<-data.frame()
pops<-c("PWS","TB","SS")
for (i in 1:3){
    df<-read.csv(paste0("../Output/Ne/Jorde-Ryman_Ne.estimates_", pops[i],"_G3.csv"), row.names = 1)
    df$pop<-pops[i]
    ne<-rbind(ne, df)
}

ne$year<-apply(ne["pop2"],1, function(x) {if (x=="96") x=1996
                   else if (x==6) x=2006
                   else if (x==7) x=2007
                   else if (x=="17") x=2017})
ne2<-ne[c(1,4,6,7,10,12,13,15),]
ne2$pop<-factor(ne2$pop, levels=c("TB","PWS","SS"))

ggplot(ne2, aes(x=year, y=Ne, color=pop))+
    geom_point(size=2)+
    geom_errorbar(aes(ymin = CI.low, ymax = CI.up), width = 0.2)+
    geom_path()+ylab("Estiamted Ne")+xlab("Year")+
    theme_classic()+
    scale_color_manual(values=cols)

ggsave("../Output/Ne/Jorde-Ryman_Ne.estimates_3Populations_G3.png", width = 5, height = 3, dpi=300)



# Pi null distribution

1. Create persite theta.pest.gz files in angsd


/home/jamcgirr/apps/angsd/misc/thetaStat  print /home/ktist/ph/data/angsd/theta/PWS91_maf00.thetas.idx | gzip > /home/ktist/ph/data/angsd/theta/PWS91_maf00_thetas.pestPG.gz

# Run printTheta.sh at farm

2. run R scripts at farm to create null distribution of genome-wide thetas

Run angsd_theta_siteshuffle_null.sh at farm, which runs Pi_shuffle_pws.R - Takes long time, so create a script for each pop.year combination and run separately

Output from theta shuffling results are in Data/shuffle/theta.siteshuffle.50000.PWS91_PWS96.csv.gz

3. Calculate p-values using the results from shuffling and plot the results

#from codEvol angsd_theta_siteshuffle_null_stats.R

###########################
# load functions
###########################
require(data.table)
require(plyr)
require(ggplot2)
require(RColorBrewer)


#####################
# read in and prep data
#####################

years<-c("PWS91","PWS96","PWS07","PWS17")
comb<-t(combn(years, 2))
# max theta per genome from reshuffling (all sites) from angsd_theta_siteshuffle_null.r

chrmax <- fread('../Data/new_vcf/chr_sizes.bed')
chrmax<-chrmax[,-2]
colnames(chrmax)<-c("chr", "len")
chrmax$start<-c(0,cumsum(chrmax$len)[1:(nrow(chrmax)-1)])

chrmax$end<-cumsum(chrmax$len)
chrmax$middle<-(chrmax$end-chrmax$start)/2+chrmax$start

#setkey(chrmax, chr)

#Functions to calculate p-values from codEvol
calcpG <- function(thetachange, null){ # for increases in theta
  return((sum(null > thetachange)+1)/(length(null)+1)) # equation from North et al. 2002 Am J Hum Gen
}
calcpL <- function(thetachange, null){ # for decreases in theta
  return((sum(null < thetachange)+1)/(length(null)+1)) # equation from North et al. 2002 Am J Hum Gen
}


cols <- brewer.pal(4, 'Paired')[rep(1:2,13)]
Datall<-data.table()
for (p in 1: nrow(comb)){
    # max theta per genome from reshuffling (all sites) from angsd_theta_siteshuffle_null.r
    null<-fread(paste0('../Data/shuffle/theta.siteshuffle.50000.', comb[p,1],"_",comb[p,2],'.csv.gz'))
    
    #upper and lower 95%
    null[, .(tWd_l95 = quantile(mintWd, 0.05), tWd_u95 = quantile(maxtWd, probs = 0.95),
                tPd_l95 = quantile(mintPd, 0.05), tPd_u95 = quantile(maxtPd, probs = 0.95),
                tDd_l95 = quantile(mintDd, 0.05), tDd_u95 = quantile(maxtDd, probs = 0.95))]

    #assign(paste0("null.",comb[p,1],"_",comb[p,2]), null)    
    
    # sliding windows theta change (GATK sites) from angsd_theta_siteshuffle_null.r
    dat<-fread(paste0('../Data/shuffle/theta_change_region_50000.', comb[p,1],"_",comb[p,2],'.csv.gz'), drop = 1)
    dat[,pop:=paste0(comb[p,1],"_",comb[p,2])]
    
    dat<-merge(dat, chrmax[,c("chr","start")], by.x="Chromo", by.y = "chr")
    dat[, POSgen := WinCenter + start]
    dat[,start := NULL] #remove start
    
    #calculate p-values
    #1. thetaW loci
    dat[tWd > 0, tWd.p := calcpG(tWd, null$maxtWd), by = .(Chromo, WinCenter)] # thetaW  loci
    dat[tWd <= 0, tWd.p := calcpL(tWd, null$mintWd), by = .(Chromo, WinCenter)]
    #2. theta pi
    dat[tPd > 0, tPd.p := calcpG(tPd, null$maxtPd), by = .(Chromo, WinCenter)] # theta pi
    dat[tPd <= 0, tPd.p := calcpL(tPd, null$mintPd), by = .(Chromo, WinCenter)]
    
    #Tajima's D
    dat[tDd > 0, tDd.p := calcpG(tDd, null$maxtDd), by = .(Chromo, WinCenter)] # tajima's D
    dat[tDd <= 0, tDd.p := calcpL(tDd, null$mintDd), by = .(Chromo, WinCenter)]

    write.csv(dat, file=gzfile(paste0('../Output/Pi/Shuffle/theta_siteshuffle_', comb[p,1],"_",comb[p,2],'.csv.gz')))
    
    Datall<-rbind(Datall, dat)
}

write.csv(Datall, file=gzfile(paste0('../Output/Pi/Shuffle/theta_siteshuffle_PWS_summary.csv.gz')))
   

## Plot the results

#chromosome number locations
winsz = 5e4 

#Changes in Pi between years
Datall$Chromo<-factor(Datall$Chromo, levels=c(paste0("chr",1:26)))
Datall$pop<-factor(Datall$pop, levels=c("PWS91_PWS96","PWS91_PWS07","PWS91_PWS17","PWS96_PWS07","PWS96_PWS17","PWS07_PWS17"))

ggplot(Datall, aes(POSgen, tPd/winsz, color = Chromo)) + 
    geom_point(size = 0.5, alpha = 0.3) +
    facet_wrap(~pop, ncol = 1) +
    scale_color_manual(values = cols, guide="none") +
    ylab('Change in pi per site')+xlab("Chromosome")+
    ggtitle("Changes in Pi")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave(paste0('../Output/Pi/Shuffle/Changes_in_Pi_PWS.png'), width = 7.5, height = 9, dpi = 300)
    
# plot theta_Waterson change
ggplot(Datall, aes(POSgen, tWd/winsz, color = Chromo)) + 
  geom_point(size = 0.5, alpha = 0.3) +
  scale_color_manual(values = cols, guide="none") +
    facet_wrap(~pop, ncol = 1) +
  ylab('Change in Wattersons theta per site')+xlab("Chromosome")+
  ggtitle("Changes in Pi")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave('../Output/Pi/Shuffle/Changes_in_thetaW_PWS.png', width = 7.5, height = 9, dpi = 300)

# plot Tajima's D change
ggplot(Datall, aes(POSgen, tDd, color = Chromo)) + 
    geom_point(size = 0.5, alpha = 0.3) +
    scale_color_manual(values = cols,guide="none") +
    facet_wrap(~pop, ncol = 1) +
    ylab('Change in Tajimas D per window')+xlab("Chromosome")+
    ggtitle("Changes in Tajima's D")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave('../Output/Pi/Shuffle/Changes_in_TajimasD_PWS.png', width = 7.5, height = 9, dpi = 300)

# plot pi p-value vs. position 
cols <- brewer.pal(4, 'Paired')[rep(1:2,13)]
Datall$Chromo<-factor(Datall$Chromo, levels=c(paste0("chr",1:26)))
Datall$pop<-factor(Datall$pop, levels=c("PWS91_PWS96","PWS91_PWS07","PWS91_PWS17","PWS96_PWS07","PWS96_PWS17","PWS07_PWS17"))

ggplot(Datall, aes(POSgen, -log10(tPd.p)*sign(tPd), color = Chromo)) + 
    geom_point(size = 0.2, alpha = 0.3) +
    facet_wrap(~pop, ncol = 1) +
    scale_color_manual(values = cols, guide="none") +xlab("Chromosome")+
    ylab("log10(P-value)")+
    geom_hline(yintercept = log10(0.05), linetype = 'dashed', color = 'grey') +
    geom_hline(yintercept = -log10(0.05), linetype = 'dashed', color = 'grey')+
    ggtitle("P-values for changes in Pi")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave('../Output/Pi/Shuffle/Changes_in_Pi.siteshuffle.p-values_PWS.png', width = 7.5, height =11, units = 'in', dpi = 300)


# plot thetaW p-value vs. position (all loci)
ggplot(Datall, aes(POSgen, -log10(tWd.p)*sign(tWd), color = Chromo)) + 
  geom_point(size = 0.2, alpha = 0.3) +
  facet_wrap(~pop, ncol = 1) +
  scale_color_manual(values = cols, guide="none") +xlab("Chromosome")+
    ylab("log10(P-value)")+
  geom_hline(yintercept = log10(0.05), linetype = 'dashed', color = 'grey') +
  geom_hline(yintercept = -log10(0.05), linetype = 'dashed', color = 'grey')+
      ggtitle("P-values for changes in Theta")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave('../Output/Pi/Shuffle/Changes_in_thetaW.siteshuffle.p-values_PWS.png', width = 7.5, height =11, units = 'in', dpi = 300)

#plot Tajama's D p-value vs. position
ggplot(Datall, aes(POSgen, -log10(tDd.p)*sign(tDd), color = Chromo)) + 
    geom_point(size = 0.2, alpha = 0.3) +
    facet_wrap(~pop, ncol = 1) +
    scale_color_manual(values = cols, guide="none") +xlab("Chromosome")+
    ylab("log10(P-value)")+
    geom_hline(yintercept = log10(0.05), linetype = 'dashed', color = 'grey') +
    geom_hline(yintercept = -log10(0.05), linetype = 'dashed', color = 'grey')+
    ggtitle("P-values for changes in Tajima's D")+
    scale_x_continuous(breaks=chrmax$middle, labels=1:26)+
    theme_bw()
ggsave('../Output/Pi/Shuffle/Changes_in_TajimaD.siteshuffle.p-values_PWS.png', width = 7.5, height =11, units = 'in', dpi = 300)

4. Outlier regions

#################
# print outliers
#################

Pi_outliers<-Datall[tPd.p < 0.05,]
Theta_outliers<-Datall[tWd.p < 0.05,]
TajimaD_outliers<-Datall[tDd.p < 0.05,] #no outliers

pi<-data.frame(table(Pi_outliers$pop, Pi_outliers$Chromo))
the<-data.frame(table(Theta_outliers$pop, Theta_outliers$Chromo))
D<-data.frame(table(TajimaD_outliers$pop, TajimaD_outliers$Chromo))

#plot PWS91-96, 96-07, and 07-17
yrs<-c("PWS91_PWS96","PWS96_PWS07","PWS07_PWS17")
col3<-brewer.pal(4,"PuRd")[2:4]

pi2<-pi[pi$Var1 %in% yrs,]
pi2$Var1<-factor(pi2$Var1, levels=yrs)
ggplot(pi2, aes(x=Var2, y=Freq, fill=Var1))+
    geom_bar(stat="identity",position=position_dodge(width=0.8))+
    scale_fill_manual(values=col3)+
    theme_classic()+
    theme(axis.text.x = element_text(angle=45, hjust=1), legend.title = element_blank())+
    ggtitle(expression(paste("Changes in ", pi)))+
    xlab('')+ylab('Number of regions with P<0.05')
ggsave("../Output/Pi/Shuffle/Pi_significant_perChrom_perPop.png", width = 8, height = 4, dpi=300) 

th2<-the[the$Var1 %in% yrs,]
th2$Var1<-factor(th2$Var1, levels=yrs)
ggplot(th2, aes(x=Var2, y=Freq, fill=Var1))+
    geom_bar(stat="identity",position=position_dodge(width=0.8))+
    scale_fill_manual(values=col3)+
    theme_classic()+
    theme(axis.text.x = element_text(angle=45, hjust=1), legend.title = element_blank())+
    ggtitle(paste0("Changes in theta"))+
    xlab('')+ylab('Number of regions with P<0.05')
ggsave("../Output/Pi/Shuffle/Theta_significant_perChrom_perPop.png", width = 8, height = 4, dpi=300) 

D2<-D[D$Var1 %in% yrs,]
D2$Var1<-factor(D2$Var1, levels=yrs)
ggplot(D2, aes(x=Var2, y=Freq, fill=Var1))+
    geom_bar(stat="identity",position=position_dodge(width=0.8))+
    scale_fill_manual(values=col3)+
    theme_classic()+
    theme(axis.text.x = element_text(angle=45, hjust=1), legend.title = element_blank())+
     ggtitle(paste0("Changes in Tajima's D"))+
    xlab('')+ylab('Number of regions with P>0.05')
ggsave("../Output/Pi/Shuffle/Pi_significant_perChrom_perPop.png", width = 8, height = 4, dpi=300) 


sum<-data.frame(table(Pi_outliers$pop))
sum2<-data.frame(table(Theta_outliers$pop))
#sum3<-data.frame(table(TajimaD_outliers$pop)) no outliers

sum<-cbind(sum, sum2$Freq)
colnames(sum)<-c("Pops", "Pi", "Theta")
knitr::kable(t(sum))
  • Most differences exist between 1996 and 2007
  • Chr25 has the most significant regions for changes in Pi and Theta s
LS0tCnRpdGxlOiAiRXN0aW1hdGVOZSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICAgIHRvYzogdHJ1ZSAKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgICAgdGhlbWU6IGx1bWVuCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCiMgRXN0aW1hdGUgZWZmZWN0aXZlIHBvcHVsYXRpb24gc2l6ZSAoTmUpIG9mIFBXUyBmcm9tIGFsbGVsZSBmcmVxdW5jeSBjaGFnbmVzIAogCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNvdXJjZSgiLi4vUnNjcmlwdHMvQmFzZVNjcmlwdHMuUiIpCnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShwbHlyKQpyZXF1aXJlKFJDb2xvckJyZXdlcikKbGlicmFyeShwb29sU2VxKQpgYGAKCiMjIE5lc3QvUG9vbFNlcSBwYWNrYWdlIGlzIHVzZWQuIApSZWY6IGRvaTogMTAuMTUzNC9nZW5ldGljcy4xMTYuMTkxMTk3CgoKMS4gU3Vic2V0IFZDRiBmaWxlcyBieSBwb3B1bGF0aW9uICAKYGBge2Jhc2ggZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI3N1YnNldCBhIFZDRiBmaWxlIGJ5IHBvcHVsYXRpb24gKHN1YnNldF92Y2ZfYnlQb3BQV1Muc2gpCgojIS9iaW4vYmFzaAojU0JBVENIIC0tam9iLW5hbWU9c3Vic2V0UG9wCiNTQkFUQ0ggLS1tZW09MTZHIAojU0JBVENIIC0tbm9kZXM9NCAKI1NCQVRDSCAtLW50YXNrcz04IAojU0JBVENIIC1lIHN1YnNldFBvcC5lcnIgIAojU0JBVENIIC0tdGltZT03MjowMDowMCAgCiNTQkFUQ0ggLS1tYWlsLXVzZXI9a3Rpc3RAdWNkYXZpcy5lZHUgIyNlbWFpbCB5b3Ugd2hlbiBqb2Igc3RhcnRzLGVuZHMsZXRjCiNTQkFUQ0ggLS1tYWlsLXR5cGU9QUxMCgojU0JBVENIIC1wIGhpZ2ggIAoKbW9kdWxlIGxvYWQgYmNmdG9vbHMKCmJjZnRvb2xzIHZpZXcgLU96IC1TIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvcG9wdWxhdGlvbi9QV1MwNy50eHQgLS10aHJlYWRzIDE2IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvUFdTb25seV9OUzAuNV9tYWYwNS52Y2YuZ3ogPiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vUFdTb25seTA3X21hZjA1LnZjZi5neiAKYmNmdG9vbHMgdmlldyAtT3ogLVMgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXUzE3LnR4dCAtLXRocmVhZHMgMTYgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9QV1Nvbmx5X05TMC41X21hZjA1LnZjZi5neiA+IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvcG9wdWxhdGlvbi9QV1Nvbmx5MTdfbWFmMDUudmNmLmd6IApiY2Z0b29scyB2aWV3IC1PeiAtUyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vUFdTOTEudHh0IC0tdGhyZWFkcyAxNiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL1BXU29ubHlfTlMwLjVfbWFmMDUudmNmLmd6ID4gL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHk5MV9tYWYwNS52Y2YuZ3ogCmJjZnRvb2xzIHZpZXcgLU96IC1TIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvcG9wdWxhdGlvbi9QV1M5Ni50eHQgLS10aHJlYWRzIDE2IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvUFdTb25seV9OUzAuNV9tYWYwNS52Y2YuZ3ogPiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vUFdTb25seTk2X21hZjA1LnZjZi5neiAKCmBgYAoKMi4gQ2FsY3VsYXRlIGFsbGVsZSBmcmVxdWVuY3kgdXNpbmcgVkNGdG9vbHMgIApgYGB7YmFzaCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojQ2FsY3VsYXRlIGFsbGVsZSBmcmVxdWVuY3kgdXNpbmcgVkNGdG9vbHMgKGNhbGN1bGF0ZUFGX1ZDRnRvb2xzLnNoKQoKIyEvYmluL2Jhc2ggLWwKI1NCQVRDSCAtLWpvYi1uYW1lPWNhbGN1bGF0ZUFGCiNTQkFUQ0ggLS1tZW09MTZHCiNTQkFUQ0ggLS1ub2Rlcz00IAojU0JBVENIIC0tbnRhc2tzPTggCiNTQkFUQ0ggLS1lcnJvciBjYWxjdWxhdGVBRi5lcnIKI1NCQVRDSCAtLXRpbWU9NDg6MDA6MDAKI1NCQVRDSCAtLW1haWwtdXNlcj1rdGlzdEB1Y2RhdmlzLmVkdSAjI2VtYWlsIHlvdSB3aGVuIGpvYiBzdGFydHMsZW5kcyxldGMKI1NCQVRDSCAtLW1haWwtdHlwZT1BTEwKI1NCQVRDSCAtcCBoaWdoIAoKbW9kdWxlIGxvYWQgdmNmdG9vbHMKCnZjZnRvb2xzIC0tZ3p2Y2YgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHkwN19tYWYwNS52Y2YuZ3ogLS1mcmVxIC0tb3V0IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvQUYvUFdTb25seTA3X21hZjA1X2ZyZXEgCnZjZnRvb2xzIC0tZ3p2Y2YgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHkxN19tYWYwNS52Y2YuZ3ogLS1mcmVxIC0tb3V0IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvQUYvUFdTb25seTE3X21hZjA1X2ZyZXEgCnZjZnRvb2xzIC0tZ3p2Y2YgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHk5MV9tYWYwNS52Y2YuZ3ogLS1mcmVxIC0tb3V0IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvQUYvUFdTb25seTkxX21hZjA1X2ZyZXEgCnZjZnRvb2xzIC0tZ3p2Y2YgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHk5Nl9tYWYwNS52Y2YuZ3ogLS1mcmVxIC0tb3V0IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvQUYvUFdTb25seTk2X21hZjA1X2ZyZXEgCmBgYAoKMy4gT2J0YWluIHJlYWQgZGVwdGhzIGZyb20gVkNGIGZpbGVzICAKYGBge2Jhc2ggZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KI09idGFpbiBkZXB0aCBpbmZvcm1hdGlvbiBmcm9tIFZDRiBmaWxlcyAoZXh0cmFjdF9jb3ZlcmFnZVBXUy5zaCkKCiMhL2Jpbi9iYXNoCiNTQkFUQ0ggLS1qb2ItbmFtZT1leHRyYWN0X2NvdmVyYWdlIAojU0JBVENIIC0tbWVtPTE2RyAKI1NCQVRDSCAtLW50YXNrcz0xIAojU0JBVENIIC1lIGV4dHJhY3RfY292ZXJhZ2UuZXJyICAKI1NCQVRDSCAtLXRpbWU9NDg6MDA6MDAgIAojU0JBVENIIC0tbWFpbC11c2VyPWt0aXN0QHVjZGF2aXMuZWR1ICMjZW1haWwgeW91IHdoZW4gam9iIHN0YXJ0cyxlbmRzLGV0YwojU0JBVENIIC0tbWFpbC10eXBlPUFMTAojU0JBVENIIC1wIGhpZ2ggIAoKbW9kdWxlIGxvYWQgYmNmdG9vbHMKYmNmdG9vbHMgcXVlcnkgLWYgJyVDSFJPTSAgJVBPUyAgJUlORk8vRFBcbicgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHkwN19tYWYwNS52Y2YuZ3ogPiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL2RlcHRoL1BXU29ubHkwN19tYWYwNS5kZXB0aC5pbmZvIApiY2Z0b29scyBxdWVyeSAtZiAnJUNIUk9NICAlUE9TICAlSU5GTy9EUFxuJyAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL3BvcHVsYXRpb24vUFdTb25seTE3X21hZjA1LnZjZi5neiA+IC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvZGVwdGgvUFdTb25seTE3X21hZjA1LmRlcHRoLmluZm8gCmJjZnRvb2xzIHF1ZXJ5IC1mICclQ0hST00gICVQT1MgICVJTkZPL0RQXG4nIC9ob21lL2t0aXN0L3BoL2RhdGEvbmV3X3ZjZi9NRDcwMDAvcG9wdWxhdGlvbi9QV1Nvbmx5OTFfbWFmMDUudmNmLmd6ID4gL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9kZXB0aC9QV1Nvbmx5OTFfbWFmMDUuZGVwdGguaW5mbyAKYmNmdG9vbHMgcXVlcnkgLWYgJyVDSFJPTSAgJVBPUyAgJUlORk8vRFBcbicgL2hvbWUva3Rpc3QvcGgvZGF0YS9uZXdfdmNmL01ENzAwMC9wb3B1bGF0aW9uL1BXU29ubHk5Nl9tYWYwNS52Y2YuZ3ogPiAvaG9tZS9rdGlzdC9waC9kYXRhL25ld192Y2YvTUQ3MDAwL2RlcHRoL1BXU29ubHk5Nl9tYWYwNS5kZXB0aC5pbmZvIAoKYGBgCgojIyBVc2UgcG9vbFNlcSB0byBjYWxjdWFsdGUgTmUgCgojIyMgMS4gUmVhZCBBRiAoZnJxKSBmaWxlcyBhbmQgZmlsdGVyIG91dCBleHRyZW1lIHZhbHVlcyBhbmQgdW5pbmZvcm1hdGl2ZSBsb2NpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzb3VyY2UoIi4uL1JzY3JpcHRzL0Jhc2VTY3JpcHRzLlIiKQpsaWJyYXJ5KHBvb2xTZXEpCgpwb3BzPC1jKCJQV1M5MSIsIlBXUzk2IiwiUFdTMDciLCJQV1MxNyIpCnlyPC1jKDkxLDk2LCIwNyIsMTcpCiNSZWFkIHRoZSBhbGxlbGUgZnJlcSBkYXRhIGZvciBQV1MKCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9BRi9QV1Nvbmx5Iix5cltpXSwiX21hZjA1X2ZyZXEuZnJxIiksc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLGhlYWRlciA9IEZBTFNFLCBza2lwPTEsIGNvbC5uYW1lcyA9IGMoImNociIsInBvcyIsIm5fYWxsZWxlIiwibl9zYW1wbGUiLCJNYWpvckFGIiwiTUFGIikpCiAgICBkZiRtYWY8LXN1YnN0cihkZiRNQUYsIDMsMTApCiAgICBkZjwtZGZbLGMoMSwyLDcpXQogICAgZGYkbWFmPC1hcy5udW1lcmljKGRmJG1hZikKICAgIGFzc2lnbihwYXN0ZTAoInB3cyIsaSksZGYpCn0KCiNjb21iaW5lIEFGIGZvciBhbGwgeWVhcnMKcHdzPC1jYmluZChwd3MxLCBwd3MyWywzXSxwd3MzWywzXSxwd3M0WywzXSkKY29sbmFtZXMocHdzKTwtYygiY2hyIiwicG9zIiwiRjAiLCJGMSIsIkYyIiwiRjMiKQp3cml0ZS5jc3YocHdzLCAiLi4vT3V0cHV0L05lL1BXU29ubHlfQUYuY3N2IikKCiNSZWFkIGRlcHRoIGluZm9ybWF0aW9uCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9kZXB0aC9QV1Nvbmx5Iix5cltpXSwiX21hZjA1LmRlcHRoLmluZm8iKSwgaGVhZGVyPUYpCiAgICBjb2xuYW1lcyhkZik8LWMoImNociIsInBvcyIsImRlcHRoIikKICAgIGFzc2lnbihwYXN0ZTAoIkQiLGkpLGRmKQp9CiNjb21iaW5lIERlcHRoIGZvciBhbGwgeWVhcnMKRFA8LWNiaW5kKEQxLCBEMlssM10sRDNbLDNdLEQ0WywzXSkKY29sbmFtZXMoRFApPC1jKCJjaHIiLCJwb3MiLCJGMCIsIkYxIiwiRjIiLCJGMyIpCndyaXRlLmNzdihEUCwiLi4vT3V0cHV0L05lL1BXU29ubHlfcmVhZF9kZXB0aC5jc3YiKQoKI0ZpbmQgU05QcyB3aXRoIGV4dHJlbWUgdmFsdWVzIGFuZCB1bmluZm9ybWF0aXZlIGxvY2kgYW5kIHJlbW92ZSB0aGVtCnJldGFpbjwtY2hlY2tTTlAocHdzWywiRjAiXSxwd3NbLCJGMyJdLERQWywiRjAiXSwgRFBbLCJGMyJdKQpsZW5ndGgocmV0YWluW3JldGFpbj09Rl0pICM2NTMxNyB3aWxsIGJlIHJlbW92ZWQKCiNmaWx0ZXJlZCB0aGUgc25wIGRhdGFzZXQKcHdzX2ZpbHRlcmVkPC1wd3NbcmV0YWluLF0KRFBfZmlsdGVyZWQ8LURQW3JldGFpbixdCgojTG9vayBhdCBGMCBhbmQgRjEKcmV0YWluMTwtY2hlY2tTTlAocHdzX2ZpbHRlcmVkWywiRjAiXSxwd3NfZmlsdGVyZWRbLCJGMSJdLERQX2ZpbHRlcmVkWywiRjAiXSwgRFBfZmlsdGVyZWRbLCJGMSJdKQpsZW5ndGgocmV0YWluMVtyZXRhaW4xPT1GXSkgIzAKCnJldGFpbjI8LWNoZWNrU05QKHB3c19maWx0ZXJlZFssIkYwIl0scHdzX2ZpbHRlcmVkWywiRjIiXSxEUF9maWx0ZXJlZFssIkYwIl0sIERQX2ZpbHRlcmVkWywiRjIiXSkKbGVuZ3RoKHJldGFpbjJbcmV0YWluMj09Rl0pICMwCgpyZXRhaW4zPC1jaGVja1NOUChwd3NfZmlsdGVyZWRbLCJGMSJdLHB3c19maWx0ZXJlZFssIkYyIl0sRFBfZmlsdGVyZWRbLCJGMSJdLCBEUF9maWx0ZXJlZFssIkYyIl0pCmxlbmd0aChyZXRhaW4zW3JldGFpbjM9PUZdKSAjMjI0NzkKCnJldGFpbjQ8LWNoZWNrU05QKHB3c19maWx0ZXJlZFssIkYyIl0scHdzX2ZpbHRlcmVkWywiRjMiXSxEUF9maWx0ZXJlZFssIkYyIl0sIERQX2ZpbHRlcmVkWywiRjMiXSkKbGVuZ3RoKHJldGFpbjRbcmV0YWluND09Rl0pICMzNDgwOQoKYGBgCgojIyMgMi4gUnVuIHBvb2xTZXEgdG8gb2J0YWluIHNob3J0LXRlcm0gTmUgdmFsdWVzIApQV1MgYmV0d2VlbiAxOTkxIGFuZCAyMDE3ICAKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbWV0aG9kczwtYygiVy5wbGFuSSIsIlcucGxhbklJIiwiSlIucGxhbkkiLCJKUi5wbGFuSUkiLCJQLnBsYW5JIiwiUC5wbGFuSUkiLCJQLmFsdC4xc3RlcC5wbGFuSUkiKQoKI2NhbGN1YWx0ZSBOZSBmb3IgUFdTOTEtUFdTMTcgcGVyaW9kIApwd3NfTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIHB3c19OZSROZVtpXTwtZXN0aW1hdGVOZShwMD1wd3NfZmlsdGVyZWRbLCJGMCJdLCBwdD1wd3NfZmlsdGVyZWRbLCJGMyJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYzIl0sIHQ9NSwgCiAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAscG9vbFNpemU9Yyg1OCw1NikpCiAgICBwd3NfTmUkTmVfMTAwMDBbaV08LWVzdGltYXRlTmUocDA9cHdzX2ZpbHRlcmVkWywiRjAiXSwgcHQ9cHdzX2ZpbHRlcmVkWywiRjMiXSwgY292MD1EUF9maWx0ZXJlZFssIkYwIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMyJdLCB0PTUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwMCxwb29sU2l6ZT1jKDU4LDU2KSkKICAgIAp9CndyaXRlLmNzdihwd3NfTmUsIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0aW9uX1BXU29ubHk5MS0xN192Y2ZBRi5jc3YiKQojUGxhbkkgcmVxdWlyZXMgTmNlbnN1cywgUGxhbklJIGRvZXMgbm90IHJlcXVpcmUgTmNlbnN1cwpgYGAKCgpgYGB7ciBldmFsPVRSVUV9CnB3c19OZTwtcmVhZC5jc3YoIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0aW9uX1BXU29ubHk5MS0xN192Y2ZBRi5jc3YiLCByb3cubmFtZXMgPSAxKQpsaWJyYXJ5KGtuaXRyKQprYWJsZShwd3NfTmUsIGNhcHRpb24gPSAiRXN0aWFtdGVkIE5lIikKCmBgYAoKUGxhbkkgcmVxdWlyZXMgJ05jZW5zdXMnLGFuZCBQbGFuSUkgZG9lcyBub3QgcmVxdWlyZSBOY2Vuc3VzLiBOY2Vuc3VzID0xMDAwIFtOZV0gYW5kIDEwMDAwIE5lXzEwMDAwLgpEb2VzIG5vdCBtYWtlIG11Y2ggZGlmZmVyZW5jZSBhZnRlciAxMDAwMAoKIyMjIDMuIEVzdGltYXRlIE5lIGZvciBlYWNoIHRpbWUgcG9pbnQgIApgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojZnVydGhlciBmaWx0ZXJlZCB0aGUgc25wIGRhdGFzZXQKcHdzX2ZpbHRlcmVkPC1wd3NfZmlsdGVyZWRbcmV0YWluMyxdCkRQX2ZpbHRlcmVkPC1EUF9maWx0ZXJlZFtyZXRhaW4zLF0KcmV0YWluNDwtY2hlY2tTTlAocHdzX2ZpbHRlcmVkWywiRjIiXSxwd3NfZmlsdGVyZWRbLCJGMyJdLERQX2ZpbHRlcmVkWywiRjIiXSwgRFBfZmlsdGVyZWRbLCJGMyJdKQpsZW5ndGgocmV0YWluNFtyZXRhaW40PT1GXSkKcHdzX2ZpbHRlcmVkPC1wd3NfZmlsdGVyZWRbcmV0YWluNCxdCkRQX2ZpbHRlcmVkPC1EUF9maWx0ZXJlZFtyZXRhaW40LF0KCgpOZTwtZGF0YS5mcmFtZShtZXRob2RzPW1ldGhvZHMpCmZvciAoaSBpbiAxOiBsZW5ndGgobWV0aG9kcykpewogICAgTmUkTmUwMV90MVtpXTwtZXN0aW1hdGVOZShwMD1wd3NfZmlsdGVyZWRbLCJGMCJdLCBwdD1wd3NfZmlsdGVyZWRbLCJGMSJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYxIl0sIHQ9MSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9bWV0aG9kc1tpXSwgTmNlbnN1cz0xMDAwMCxwb29sU2l6ZT1jKDU4LDcyKSkKICAgIE5lJE5lMTJfdDJbaV08LWVzdGltYXRlTmUocDA9cHdzX2ZpbHRlcmVkWywiRjEiXSwgcHQ9cHdzX2ZpbHRlcmVkWywiRjIiXSwgY292MD1EUF9maWx0ZXJlZFssIkYxIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMiJdLCB0PTEuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwLHBvb2xTaXplPWMoNzIsNDYpKQogICAgTmUkTmUyM190MltpXTwtZXN0aW1hdGVOZShwMD1wd3NfZmlsdGVyZWRbLCJGMiJdLCBwdD1wd3NfZmlsdGVyZWRbLCJGMyJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjIiXSwgY292dD1EUF9maWx0ZXJlZFssIkYzIl0sIHQ9MS43LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPW1ldGhvZHNbaV0sIE5jZW5zdXM9MTAwMDAscG9vbFNpemU9Yyg0Niw1NikpCn0KCndyaXRlLmNzdihOZSwgIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0aW9uX1BXU29ubHlfZWFjaFRpbWVQZXJpb2RfdmNmQUYuY3N2IikKTmUKCmBgYAoKCiMjIyA0LiBQbG90IHRoZSByZXN1bHRzCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmNvbG5hbWVzKE5lKVsyOjRdPC1jKCJUMSIsIlQyIiwiVDMiKQpuZW08LXJlc2hhcGUyOjptZWx0KE5lLCBpZC52YXJzPSJtZXRob2RzIix2YWx1ZS5uYW1lID0iTmUiKQoKZ2dwbG90KG5lbSwgYWVzKHg9dmFyaWFibGUsIHk9TmUsIGNvbG9yPW1ldGhvZHMpKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX2NsYXNzaWMoKSt5bGFiKCJOZSIpK3hsYWIoIlRpbWUgcGVyaW9kIikrCiAgICBnZW9tX3BhdGgoYWVzKHg9dmFyaWFibGUsIHk9TmUsIGdyb3VwPW1ldGhvZHMsY29sb3I9bWV0aG9kcykpKwogICAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkrZ2d0aXRsZSgiUFdTIikKZ2dzYXZlKCIuLi9PdXRwdXQvTmUvTmVfZXN0aW1hdGVzX292ZXJ0aW1lX1BXUy5wbmciLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQsIGRwaT0xNTApCmBgYAohW10oLi4vT3V0cHV0L05lL05lX2VzdGltYXRlc19vdmVydGltZV9QV1MucG5nKSAgCgoqIENvbXBhcmUgdGhlIHJlc3VsdHMgd2l0aCBQV1Nvbmx5X21hZjAuMDUgdnMuIFBXU19tYWYwLjA1IAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcG9wczwtYygiUFdTOTEiLCJQV1M5NiIsIlBXUzA3IiwiUFdTMTciKQp5cjwtYyg5MSw5NiwiMDciLDE3KQpmb3IgKGkgaW4gMTpsZW5ndGgocG9wcykpewogICAgZGY8LXJlYWQudGFibGUocGFzdGUwKCIuLi9EYXRhL25ld192Y2YvQUYvUFdTIix5cltpXSwiX21hZjA1X2FmLmZycSIpLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSxoZWFkZXIgPSBGQUxTRSwgc2tpcD0xLCBjb2wubmFtZXMgPSBjKCJjaHIiLCJwb3MiLCJuX2FsbGVsZSIsIm5fc2FtcGxlIiwiTWFqb3JBRiIsIk1BRiIpKQogICAgZGYkbWFmPC1zdWJzdHIoZGYkTUFGLCAzLDEwKQogICAgZGY8LWRmWyxjKDEsMiw3KV0KICAgIGRmJG1hZjwtYXMubnVtZXJpYyhkZiRtYWYpCiAgICBhc3NpZ24ocGFzdGUwKCJwd3MiLGkpLGRmKQp9CgojY29tYmluZSBBRiBmb3IgYWxsIHllYXJzCnB3czwtY2JpbmQocHdzMSwgcHdzMlssM10scHdzM1ssM10scHdzNFssM10pCmNvbG5hbWVzKHB3cyk8LWMoImNociIsInBvcyIsIkYwIiwiRjEiLCJGMiIsIkYzIikKd3JpdGUuY3N2KHB3cywgIi4uL091dHB1dC9OZS9QV1NfQUYuY3N2IikKCiNSZWFkIGRlcHRoIGluZm9ybWF0aW9uCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9kZXB0aC9QV1MiLHlyW2ldLCJfbWFmMDUuZGVwdGguaW5mbyIpLCBoZWFkZXI9RikKICAgIGNvbG5hbWVzKGRmKTwtYygiY2hyIiwicG9zIiwiZGVwdGgiKQogICAgYXNzaWduKHBhc3RlMCgiRCIsaSksZGYpCn0KI2NvbWJpbmUgRGVwdGggZm9yIGFsbCB5ZWFycwpEUDwtY2JpbmQoRDEsIEQyWywzXSxEM1ssM10sRDRbLDNdKQpjb2xuYW1lcyhEUCk8LWMoImNociIsInBvcyIsIkYwIiwiRjEiLCJGMiIsIkYzIikKI3dyaXRlLmNzdihEUCwiLi4vT3V0cHV0L05lL1BXU19yZWFkX2RlcHRoLmNzdiIpCgojRmluZCBTTlBzIHdpdGggZXh0cmVtZSB2YWx1ZXMgYW5kIHVuaW5mb3JtYXRpdmUgbG9jaSBhbmQgcmVtb3ZlIHRoZW0KcmV0YWluPC1jaGVja1NOUChwd3NbLCJGMCJdLHB3c1ssIkYzIl0sRFBbLCJGMCJdLCBEUFssIkYzIl0pCmxlbmd0aChyZXRhaW5bcmV0YWluPT1GXSkgIzY1MzE3IHdpbGwgYmUgcmVtb3ZlZAoKI2ZpbHRlcmVkIHRoZSBzbnAgZGF0YXNldApwd3NfZmlsdGVyZWQ8LXB3c1tyZXRhaW4sXQpEUF9maWx0ZXJlZDwtRFBbcmV0YWluLF0KCiNMb29rIGF0IEYwIGFuZCBGMQpyZXRhaW4xPC1jaGVja1NOUChwd3NfZmlsdGVyZWRbLCJGMCJdLHB3c19maWx0ZXJlZFssIkYxIl0sRFBfZmlsdGVyZWRbLCJGMCJdLCBEUF9maWx0ZXJlZFssIkYxIl0pCmxlbmd0aChyZXRhaW4xW3JldGFpbjE9PUZdKSAjMAoKcmV0YWluMjwtY2hlY2tTTlAocHdzX2ZpbHRlcmVkWywiRjAiXSxwd3NfZmlsdGVyZWRbLCJGMiJdLERQX2ZpbHRlcmVkWywiRjAiXSwgRFBfZmlsdGVyZWRbLCJGMiJdKQpsZW5ndGgocmV0YWluMltyZXRhaW4yPT1GXSkgIzAKCnJldGFpbjM8LWNoZWNrU05QKHB3c19maWx0ZXJlZFssIkYxIl0scHdzX2ZpbHRlcmVkWywiRjIiXSxEUF9maWx0ZXJlZFssIkYxIl0sIERQX2ZpbHRlcmVkWywiRjIiXSkKbGVuZ3RoKHJldGFpbjNbcmV0YWluMz09Rl0pICM1ODE1CgpyZXRhaW40PC1jaGVja1NOUChwd3NfZmlsdGVyZWRbLCJGMiJdLHB3c19maWx0ZXJlZFssIkYzIl0sRFBfZmlsdGVyZWRbLCJGMiJdLCBEUF9maWx0ZXJlZFssIkYzIl0pCmxlbmd0aChyZXRhaW40W3JldGFpbjQ9PUZdKSAjOTg1NwoKbWV0aG9kczwtYygiVy5wbGFuSSIsIlcucGxhbklJIiwiSlIucGxhbkkiLCJKUi5wbGFuSUkiLCJQLnBsYW5JIiwiUC5wbGFuSUkiLCJQLmFsdC4xc3RlcC5wbGFuSUkiKQoKI2NhbGN1YWx0ZSBOZSBmb3IgUFdTOTEtUFdTMTcgcGVyaW9kIApwd3NfTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIHB3c19OZSROZVtpXTwtZXN0aW1hdGVOZShwMD1wd3NfZmlsdGVyZWRbLCJGMCJdLCBwdD1wd3NfZmlsdGVyZWRbLCJGMyJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYzIl0sIHQ9NSwgCiAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAscG9vbFNpemU9Yyg1OCw1NikpCiAgICBwd3NfTmUkTmVfMTAwMDBbaV08LWVzdGltYXRlTmUocDA9cHdzX2ZpbHRlcmVkWywiRjAiXSwgcHQ9cHdzX2ZpbHRlcmVkWywiRjMiXSwgY292MD1EUF9maWx0ZXJlZFssIkYwIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMyJdLCB0PTUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwMCxwb29sU2l6ZT1jKDU4LDU2KSkKICAgIAp9CmBgYAoKYGBge3J9CmxpYnJhcnkoa25pdHIpCnB3c19OZTwtCmthYmxlKHB3c19OZSwgY2FwdGlvbiA9ICJFc3RpYW10ZWQgTmUiKQpgYGAKCgpgYGB7ciBldmFsPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojZnVydGhlciBmaWx0ZXJlZCB0aGUgc25wIGRhdGFzZXQKcHdzX2ZpbHRlcmVkPC1wd3NfZmlsdGVyZWRbcmV0YWluMyxdCkRQX2ZpbHRlcmVkPC1EUF9maWx0ZXJlZFtyZXRhaW4zLF0KcmV0YWluNDwtY2hlY2tTTlAocHdzX2ZpbHRlcmVkWywiRjIiXSxwd3NfZmlsdGVyZWRbLCJGMyJdLERQX2ZpbHRlcmVkWywiRjIiXSwgRFBfZmlsdGVyZWRbLCJGMyJdKQpwd3NfZmlsdGVyZWQ8LXB3c19maWx0ZXJlZFtyZXRhaW40LF0KRFBfZmlsdGVyZWQ8LURQX2ZpbHRlcmVkW3JldGFpbjQsXQoKTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIE5lJE5lMDFfdDFbaV08LWVzdGltYXRlTmUocDA9cHdzX2ZpbHRlcmVkWywiRjAiXSwgcHQ9cHdzX2ZpbHRlcmVkWywiRjEiXSwgY292MD1EUF9maWx0ZXJlZFssIkYwIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMSJdLCB0PTEsIAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPW1ldGhvZHNbaV0sIE5jZW5zdXM9MTAwMDAscG9vbFNpemU9Yyg1OCw3MikpCiAgICBOZSROZTEyX3QyW2ldPC1lc3RpbWF0ZU5lKHAwPXB3c19maWx0ZXJlZFssIkYxIl0sIHB0PXB3c19maWx0ZXJlZFssIkYyIl0sIGNvdjA9RFBfZmlsdGVyZWRbLCJGMSJdLCBjb3Z0PURQX2ZpbHRlcmVkWywiRjIiXSwgdD0xLjgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9bWV0aG9kc1tpXSwgTmNlbnN1cz0xMDAwMCxwb29sU2l6ZT1jKDcyLDQ2KSkKICAgIE5lJE5lMjNfdDJbaV08LWVzdGltYXRlTmUocDA9cHdzX2ZpbHRlcmVkWywiRjIiXSwgcHQ9cHdzX2ZpbHRlcmVkWywiRjMiXSwgY292MD1EUF9maWx0ZXJlZFssIkYyIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMyJdLCB0PTEuNywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwLHBvb2xTaXplPWMoNDYsNTYpKQp9CndyaXRlLmNzdihOZSwgIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0aW9uX1BXU19lYWNoVGltZVBlcmlvZF92Y2ZBRi5jc3YiKQpOZQoKY29sbmFtZXMoTmUpWzI6NF08LWMoIlQxIiwiVDIiLCJUMyIpCm5lbTwtcmVzaGFwZTI6Om1lbHQoTmUsIGlkLnZhcnM9Im1ldGhvZHMiLHZhbHVlLm5hbWUgPSJOZSIpCgpnZ3Bsb3QobmVtLCBhZXMoeD12YXJpYWJsZSwgeT1OZSwgY29sb3I9bWV0aG9kcykpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfY2xhc3NpYygpK3lsYWIoIk5lIikreGxhYigiVGltZSBwZXJpb2QiKSsKICAgIGdlb21fcGF0aChhZXMoeD12YXJpYWJsZSwgeT1OZSwgZ3JvdXA9bWV0aG9kcyxjb2xvcj1tZXRob2RzKSkrCiAgICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKQpnZ3NhdmUoIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0ZXNfb3ZlcnRpbWVfUFdTX25vblBXU29ubHkucG5nIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCBkcGk9MTUwKQoKYGBgCiFbXSguLi9PdXRwdXQvTmUvTmVfZXN0aW1hdGVzX292ZXJ0aW1lX1BXU19ub25QV1Nvbmx5LnBuZykKCiogSGlnaGx5IHNpbWlsYXIgLWNhbiB1c2UgUEhfbWFmMDUgZGF0YQoKIyMjIDUuIENhbGN1bGF0ZSBUQiBhbmQgU1MgTmUgIAoKLSAxLiBUQgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzaXplPC1yZWFkLmNzdigiLi4vRGF0YS9wb3BpbmZvL3BvcHNpemUuY3N2IikKcG9wczwtYygiVEI5MSIsIlRCOTYiLCJUQjA2IiwiVEIxNyIpCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9BRi8iLHBvcHNbaV0sIl9tYWYwNV9hZi5mcnEiKSxzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsaGVhZGVyID0gRkFMU0UsIHNraXA9MSwgY29sLm5hbWVzID0gYygiY2hyIiwicG9zIiwibl9hbGxlbGUiLCJuX3NhbXBsZSIsIk1ham9yQUYiLCJNQUYiKSkKICAgIGRmJG1hZjwtc3Vic3RyKGRmJE1BRiwgMywxMCkKICAgIGRmPC1kZlssYygxLDIsNyldCiAgICBkZiRtYWY8LWFzLm51bWVyaWMoZGYkbWFmKQogICAgYXNzaWduKHBhc3RlMCgiQUYiLGkpLGRmKQp9CgojY29tYmluZSBBRiBmb3IgYWxsIHllYXJzCkFGPC1jYmluZChBRjEsIEFGMlssM10sQUYzWywzXSxBRjRbLDNdKQpjb2xuYW1lcyhBRik8LWMoImNociIsInBvcyIsIkYwIiwiRjEiLCJGMiIsIkYzIikKd3JpdGUuY3N2KEFGLCAiLi4vT3V0cHV0L05lL1RCX21hZjA1X0FGLmNzdiIpCgojUmVhZCBkZXB0aCBpbmZvcm1hdGlvbgpmb3IgKGkgaW4gMTpsZW5ndGgocG9wcykpewogICAgZGY8LXJlYWQudGFibGUocGFzdGUwKCIuLi9EYXRhL25ld192Y2YvZGVwdGgvIixwb3BzW2ldLCJfbWFmMDUuZGVwdGguaW5mbyIpLCBoZWFkZXI9RikKICAgIGNvbG5hbWVzKGRmKTwtYygiY2hyIiwicG9zIiwiZGVwdGgiKQogICAgYXNzaWduKHBhc3RlMCgiRCIsaSksZGYpCn0KI2NvbWJpbmUgRGVwdGggZm9yIGFsbCB5ZWFycwpEUDwtY2JpbmQoRDEsIEQyWywzXSxEM1ssM10sRDRbLDNdKQpjb2xuYW1lcyhEUCk8LWMoImNociIsInBvcyIsIkYwIiwiRjEiLCJGMiIsIkYzIikKd3JpdGUuY3N2KERQLCIuLi9PdXRwdXQvTmUvVEJfbWFmMDVfcmVhZF9kZXB0aC5jc3YiKQoKI0ZpbmQgU05QcyB3aXRoIGV4dHJlbWUgdmFsdWVzIGFuZCB1bmluZm9ybWF0aXZlIGxvY2kgYW5kIHJlbW92ZSB0aGVtCnJldGFpbjwtY2hlY2tTTlAoQUZbLCJGMCJdLEFGWywiRjMiXSxEUFssIkYwIl0sIERQWywiRjMiXSkKbGVuZ3RoKHJldGFpbltyZXRhaW49PUZdKSAjNjk3NDMKQUZfZmlsdGVyZWQ8LUFGW3JldGFpbixdCkRQX2ZpbHRlcmVkPC1EUFtyZXRhaW4sXQoKI0xvb2sgYXQgRjAgYW5kIEYxCnJldGFpbjE8LWNoZWNrU05QKEFGX2ZpbHRlcmVkWywiRjAiXSxBRl9maWx0ZXJlZFssIkYxIl0sRFBfZmlsdGVyZWRbLCJGMCJdLCBEUF9maWx0ZXJlZFssIkYxIl0pCmxlbmd0aChyZXRhaW4xW3JldGFpbjE9PUZdKSAjMAoKcmV0YWluMjwtY2hlY2tTTlAoQUZfZmlsdGVyZWRbLCJGMCJdLEFGX2ZpbHRlcmVkWywiRjIiXSxEUF9maWx0ZXJlZFssIkYwIl0sIERQX2ZpbHRlcmVkWywiRjIiXSkKbGVuZ3RoKHJldGFpbjJbcmV0YWluMj09Rl0pICMwCgpyZXRhaW4zPC1jaGVja1NOUChBRl9maWx0ZXJlZFssIkYxIl0sQUZfZmlsdGVyZWRbLCJGMiJdLERQX2ZpbHRlcmVkWywiRjEiXSwgRFBfZmlsdGVyZWRbLCJGMiJdKQpsZW5ndGgocmV0YWluM1tyZXRhaW4zPT1GXSkgIzIyNDc5CgpyZXRhaW40PC1jaGVja1NOUChBRl9maWx0ZXJlZFssIkYyIl0sQUZfZmlsdGVyZWRbLCJGMyJdLERQX2ZpbHRlcmVkWywiRjIiXSwgRFBfZmlsdGVyZWRbLCJGMyJdKQpsZW5ndGgocmV0YWluW3JldGFpbj09Rl0pIAoKbWV0aG9kczwtYygiVy5wbGFuSSIsIlcucGxhbklJIiwiSlIucGxhbkkiLCJKUi5wbGFuSUkiLCJQLnBsYW5JIiwiUC5wbGFuSUkiLCJQLmFsdC4xc3RlcC5wbGFuSUkiKQoKI2NhbGN1YWx0ZSBOZSBmb3IgMTk5MS0yMDE3IHBlcmlvZCAKQUZfTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIEFGX05lJE5lW2ldPC1lc3RpbWF0ZU5lKHAwPUFGX2ZpbHRlcmVkWywiRjAiXSwgcHQ9QUZfZmlsdGVyZWRbLCJGMyJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYzIl0sIHQ9NSwgCiAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAscG9vbFNpemU9YyhzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbMV1dLHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1s0XV0gKSkKICAgIEFGX05lJE5lXzEwMDAwW2ldPC1lc3RpbWF0ZU5lKHAwPUFGX2ZpbHRlcmVkWywiRjAiXSwgcHQ9QUZfZmlsdGVyZWRbLCJGMyJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYzIl0sIHQ9NSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPW1ldGhvZHNbaV0sIE5jZW5zdXM9MTAwMDAwLHBvb2xTaXplPSBjKHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1sxXV0sIHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1s0XV0pKQogICAgCn0Kd3JpdGUuY3N2KEFGX05lLCIuLi9PdXRwdXQvTmUvTmVfZXN0aW1hdGlvbl9UQjkxLTE3X3ZjZkFGLmNzdiIpCgprbml0cjo6a2FibGUoQUZfTmUsIGNhcHRpb24gPSAiRXN0aWFtdGVkIE5lIG9mIFRCIikKCmBgYAoKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgRXN0aW1hdGUgTmUgZm9yIGVhY2ggdGltZSBwb2ludCAgCkFGX2ZpbHRlcmVkPC1BRl9maWx0ZXJlZFtyZXRhaW4zLF0KRFBfZmlsdGVyZWQ8LURQX2ZpbHRlcmVkW3JldGFpbjMsXQpBRl9maWx0ZXJlZDwtQUZfZmlsdGVyZWRbcmV0YWluNCxdCkRQX2ZpbHRlcmVkPC1EUF9maWx0ZXJlZFtyZXRhaW40LF0KCk5lPC1kYXRhLmZyYW1lKG1ldGhvZHM9bWV0aG9kcykKZm9yIChpIGluIDE6IGxlbmd0aChtZXRob2RzKSl7CiAgICBOZSROZTAxX3QxW2ldPC1lc3RpbWF0ZU5lKHAwPUFGX2ZpbHRlcmVkWywiRjAiXSwgcHQ9QUZfZmlsdGVyZWRbLCJGMSJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYxIl0sIHQ9MSwgCiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9bWV0aG9kc1tpXSwgTmNlbnN1cz0xMDAwMCxwb29sU2l6ZT1jKHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1sxXV0sc2l6ZSRGcmVxW3NpemUkcG9wPT1wb3BzWzJdXSkpCiAgICBOZSROZTEyX3QyW2ldPC1lc3RpbWF0ZU5lKHAwPUFGX2ZpbHRlcmVkWywiRjEiXSwgcHQ9QUZfZmlsdGVyZWRbLCJGMiJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjEiXSwgY292dD1EUF9maWx0ZXJlZFssIkYyIl0sIHQ9MS44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPW1ldGhvZHNbaV0sIE5jZW5zdXM9MTAwMDAscG9vbFNpemU9YyhzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbMl1dLHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1szXV0pKQogICAgTmUkTmUyM190MltpXTwtZXN0aW1hdGVOZShwMD1BRl9maWx0ZXJlZFssIkYyIl0sIHB0PUFGX2ZpbHRlcmVkWywiRjMiXSwgY292MD1EUF9maWx0ZXJlZFssIkYyIl0sIGNvdnQ9RFBfZmlsdGVyZWRbLCJGMyJdLCB0PTEuNywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwLHBvb2xTaXplPWMoc2l6ZSRGcmVxW3NpemUkcG9wPT1wb3BzWzNdXSxzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbNF1dKSkKfQoKd3JpdGUuY3N2KE5lLCAiLi4vT3V0cHV0L05lL05lX2VzdGltYXRpb25fVEJfZWFjaFRpbWVQZXJpb2RfdmNmQUYuY3N2IikKCmNvbG5hbWVzKE5lKVsyOjRdPC1jKCJUMSIsIlQyIiwiVDMiKQpuZW08LXJlc2hhcGUyOjptZWx0KE5lLCBpZC52YXJzPSJtZXRob2RzIix2YWx1ZS5uYW1lID0iTmUiKQoKZ2dwbG90KG5lbSwgYWVzKHg9dmFyaWFibGUsIHk9TmUsIGNvbG9yPW1ldGhvZHMpKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX2NsYXNzaWMoKSt5bGFiKCJOZSIpK3hsYWIoIlRpbWUgcGVyaW9kIikrCiAgICBnZW9tX3BhdGgoYWVzKHg9dmFyaWFibGUsIHk9TmUsIGdyb3VwPW1ldGhvZHMsY29sb3I9bWV0aG9kcykpKwogICAgdGhlbWUobGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSkrZ2d0aXRsZSgiVEIiKQpnZ3NhdmUoIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0ZXNfb3ZlcnRpbWVfVEIucG5nIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCBkcGk9MTUwKQpgYGAKIVtdKC4uL091dHB1dC9OZS9OZV9lc3RpbWF0ZXNfb3ZlcnRpbWVfVEIucG5nKQoKLSAyLiBTUyAgCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpwb3BzPC1jKCJTUzk2IiwiU1MwNiIsIlNTMTciKQpmb3IgKGkgaW4gMTpsZW5ndGgocG9wcykpewogICAgZGY8LXJlYWQudGFibGUocGFzdGUwKCIuLi9EYXRhL25ld192Y2YvQUYvIixwb3BzW2ldLCJfbWFmMDVfYWYuZnJxIiksc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLGhlYWRlciA9IEZBTFNFLCBza2lwPTEsIGNvbC5uYW1lcyA9IGMoImNociIsInBvcyIsIm5fYWxsZWxlIiwibl9zYW1wbGUiLCJNYWpvckFGIiwiTUFGIikpCiAgICBkZiRtYWY8LXN1YnN0cihkZiRNQUYsIDMsMTApCiAgICBkZjwtZGZbLGMoMSwyLDcpXQogICAgZGYkbWFmPC1hcy5udW1lcmljKGRmJG1hZikKICAgIGFzc2lnbihwYXN0ZTAoIkFGIixpKSxkZikKfQojY29tYmluZSBBRiBmb3IgYWxsIHllYXJzCkFGPC1jYmluZChBRjEsIEFGMlssM10sQUYzWywzXSkKY29sbmFtZXMoQUYpPC1jKCJjaHIiLCJwb3MiLCJGMCIsIkYxIiwiRjIiKQp3cml0ZS5jc3YoQUYsICIuLi9PdXRwdXQvTmUvU1NfbWFmMDVfQUYuY3N2IikKCiNSZWFkIGRlcHRoIGluZm9ybWF0aW9uCmZvciAoaSBpbiAxOmxlbmd0aChwb3BzKSl7CiAgICBkZjwtcmVhZC50YWJsZShwYXN0ZTAoIi4uL0RhdGEvbmV3X3ZjZi9kZXB0aC8iLHBvcHNbaV0sIl9tYWYwNS5kZXB0aC5pbmZvIiksIGhlYWRlcj1GKQogICAgY29sbmFtZXMoZGYpPC1jKCJjaHIiLCJwb3MiLCJkZXB0aCIpCiAgICBhc3NpZ24ocGFzdGUwKCJEIixpKSxkZikKfQojY29tYmluZSBEZXB0aCBmb3IgYWxsIHllYXJzCkRQPC1jYmluZChEMSwgRDJbLDNdLEQzWywzXSkKY29sbmFtZXMoRFApPC1jKCJjaHIiLCJwb3MiLCJGMCIsIkYxIiwiRjIiKQp3cml0ZS5jc3YoRFAsIi4uL091dHB1dC9OZS9TU19tYWYwNV9yZWFkX2RlcHRoLmNzdiIpCgojRmluZCBTTlBzIHdpdGggZXh0cmVtZSB2YWx1ZXMgYW5kIHVuaW5mb3JtYXRpdmUgbG9jaSBhbmQgcmVtb3ZlIHRoZW0KcmV0YWluPC1jaGVja1NOUChBRlssIkYwIl0sQUZbLCJGMiJdLERQWywiRjAiXSwgRFBbLCJGMiJdKQpsZW5ndGgocmV0YWluW3JldGFpbj09Rl0pICMxMDUwOQpBRl9maWx0ZXJlZDwtQUZbcmV0YWluLF0KRFBfZmlsdGVyZWQ8LURQW3JldGFpbixdCgojTG9vayBhdCBGMCBhbmQgRjEKcmV0YWluMTwtY2hlY2tTTlAoQUZfZmlsdGVyZWRbLCJGMCJdLEFGX2ZpbHRlcmVkWywiRjEiXSxEUF9maWx0ZXJlZFssIkYwIl0sIERQX2ZpbHRlcmVkWywiRjEiXSkKbGVuZ3RoKHJldGFpbjFbcmV0YWluMT09Rl0pICMwCgpyZXRhaW4yPC1jaGVja1NOUChBRl9maWx0ZXJlZFssIkYwIl0sQUZfZmlsdGVyZWRbLCJGMiJdLERQX2ZpbHRlcmVkWywiRjAiXSwgRFBfZmlsdGVyZWRbLCJGMiJdKQpsZW5ndGgocmV0YWluMltyZXRhaW4yPT1GXSkgIzAKCnJldGFpbjM8LWNoZWNrU05QKEFGX2ZpbHRlcmVkWywiRjEiXSxBRl9maWx0ZXJlZFssIkYyIl0sRFBfZmlsdGVyZWRbLCJGMSJdLCBEUF9maWx0ZXJlZFssIkYyIl0pCmxlbmd0aChyZXRhaW4zW3JldGFpbjM9PUZdKSAjMjY1NTEKCm1ldGhvZHM8LWMoIlcucGxhbkkiLCJXLnBsYW5JSSIsIkpSLnBsYW5JIiwiSlIucGxhbklJIiwiUC5wbGFuSSIsIlAucGxhbklJIiwiUC5hbHQuMXN0ZXAucGxhbklJIikKI2NhbGN1YWx0ZSBOZSBmb3IgMTk5MS0yMDE3IHBlcmlvZCAKQUZfTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIEFGX05lJE5lW2ldPC1lc3RpbWF0ZU5lKHAwPUFGX2ZpbHRlcmVkWywiRjAiXSwgcHQ9QUZfZmlsdGVyZWRbLCJGMiJdLCBjb3YwPURQX2ZpbHRlcmVkWywiRjAiXSwgY292dD1EUF9maWx0ZXJlZFssIkYyIl0sIHQ9NSwgCiAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAscG9vbFNpemU9YyhzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbMV1dLHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1szXV0pKQogICAgQUZfTmUkTmVfMTAwMDBbaV08LWVzdGltYXRlTmUocDA9QUZfZmlsdGVyZWRbLCJGMCJdLCBwdD1BRl9maWx0ZXJlZFssIkYyIl0sIGNvdjA9RFBfZmlsdGVyZWRbLCJGMCJdLCBjb3Z0PURQX2ZpbHRlcmVkWywiRjIiXSwgdD01LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9bWV0aG9kc1tpXSwgTmNlbnN1cz0xMDAwMDAscG9vbFNpemU9IGMoc2l6ZSRGcmVxW3NpemUkcG9wPT1wb3BzWzFdXSxzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbM11dKSkKICAgIAp9CndyaXRlLmNzdihBRl9OZSwiLi4vT3V0cHV0L05lL05lX2VzdGltYXRpb25fU1M5Ni0xN192Y2ZBRi5jc3YiKQoKa25pdHI6OmthYmxlKEFGX05lLCBjYXB0aW9uID0gIkVzdGlhbXRlZCBOZSBvZiBTUyIpCgpgYGAKCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIEVzdGltYXRlIE5lIGZvciBlYWNoIHRpbWUgcG9pbnQgIApBRl9maWx0ZXJlZDwtQUZfZmlsdGVyZWRbcmV0YWluMyxdCkRQX2ZpbHRlcmVkPC1EUF9maWx0ZXJlZFtyZXRhaW4zLF0KTmU8LWRhdGEuZnJhbWUobWV0aG9kcz1tZXRob2RzKQpmb3IgKGkgaW4gMTogbGVuZ3RoKG1ldGhvZHMpKXsKICAgIE5lJE5lMDFfdDFbaV08LWVzdGltYXRlTmUocDA9QUZfZmlsdGVyZWRbLCJGMCJdLCBwdD1BRl9maWx0ZXJlZFssIkYxIl0sIGNvdjA9RFBfZmlsdGVyZWRbLCJGMCJdLCBjb3Z0PURQX2ZpbHRlcmVkWywiRjEiXSwgdD0xLCAKICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZD1tZXRob2RzW2ldLCBOY2Vuc3VzPTEwMDAwLHBvb2xTaXplPWMoc2l6ZSRGcmVxW3NpemUkcG9wPT1wb3BzWzFdXSxzaXplJEZyZXFbc2l6ZSRwb3A9PXBvcHNbMl1dKSkKICAgIE5lJE5lMTJfdDJbaV08LWVzdGltYXRlTmUocDA9QUZfZmlsdGVyZWRbLCJGMSJdLCBwdD1BRl9maWx0ZXJlZFssIkYyIl0sIGNvdjA9RFBfZmlsdGVyZWRbLCJGMSJdLCBjb3Z0PURQX2ZpbHRlcmVkWywiRjIiXSwgdD0xLjgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2Q9bWV0aG9kc1tpXSwgTmNlbnN1cz0xMDAwMCxwb29sU2l6ZT1jKHNpemUkRnJlcVtzaXplJHBvcD09cG9wc1syXV0sc2l6ZSRGcmVxW3NpemUkcG9wPT1wb3BzWzNdXSkpCn0KCndyaXRlLmNzdihOZSwgIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0aW9uX1NTX2VhY2hUaW1lUGVyaW9kX3ZjZkFGLmNzdiIpCgpjb2xuYW1lcyhOZSlbMjozXTwtYygiVDEiLCJUMiIpCm5lbTwtcmVzaGFwZTI6Om1lbHQoTmUsIGlkLnZhcnM9Im1ldGhvZHMiLHZhbHVlLm5hbWUgPSJOZSIpCgpnZ3Bsb3QobmVtLCBhZXMoeD12YXJpYWJsZSwgeT1OZSwgY29sb3I9bWV0aG9kcykpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfY2xhc3NpYygpK3lsYWIoIk5lIikreGxhYigiVGltZSBwZXJpb2QiKSsKICAgIGdlb21fcGF0aChhZXMoeD12YXJpYWJsZSwgeT1OZSwgZ3JvdXA9bWV0aG9kcyxjb2xvcj1tZXRob2RzKSkrCiAgICB0aGVtZShsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpKStnZ3RpdGxlKCJTUyIpCmdnc2F2ZSgiLi4vT3V0cHV0L05lL05lX2VzdGltYXRlc19vdmVydGltZV9TUy5wbmciLCB3aWR0aCA9IDYsIGhlaWdodCA9IDQsIGRwaT0xNTApCmBgYAohW10oLi4vT3V0cHV0L05lL05lX2VzdGltYXRlc19vdmVydGltZV9TUy5wbmcpCgojIyMgUGxvdCB0b2dldGhlciB0aGUgUC5QbGFuSUkgcmVzdWx0cwpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojUGxvdCB0b2dldGhlciAocmVzdWx0cyBmcm9tIG1hZjAuMDUgZnJlcSBmaWxlcykKbGlicmFyeSh0aWJibGUpCnBvcHM8LWMoIlBXUyIsIlRCIiwiU1MiKQpOZTwtZGF0YS5mcmFtZSgpCmZvciAoaSBpbiAxOiBsZW5ndGgocG9wcykpewogICAgZGY8LXJlYWQuY3N2KHBhc3RlMCgiLi4vT3V0cHV0L05lL05lX2VzdGltYXRpb25fIixwb3BzW2ldLCJfZWFjaFRpbWVQZXJpb2RfdmNmQUYuY3N2IiksIHJvdy5uYW1lcyA9IDEpCiAgICBkZiRwb3A8LXBvcHNbaV0gIAogICAgaWYgKGk9PTMpIHsKICAgICAgICBjb2xuYW1lcyhkZilbMjozXTwtYygiVDIiLCJUMyIpCiAgICAgICAgZGY8LWFkZF9jb2x1bW4oZGYsIFQxPU5BLCAuYWZ0ZXI9MSkKICAgIH0KICAgIGlmIChpIT0zKSBjb2xuYW1lcyhkZilbMjo0XTwtYygiVDEiLCJUMiIsIlQzIikKICAgICAgICAKICAgIE5lPC1yYmluZChOZSwgZGZbZGYkbWV0aG9kcz09IlAucGxhbklJIixdKQp9CgpOZW08LXJlc2hhcGUyOjptZWx0KE5lWywyOjVdLCBpZC52YXJzPSJwb3AiKQoKTmVtJHBvcDwtZmFjdG9yKE5lbSRwb3AsIGxldmVscz1jKCJUQiIsIlBXUyIsIlNTIikpCmdncGxvdChOZW0sIGFlcyh4PXZhcmlhYmxlLCB5PXZhbHVlLCBjb2xvcj1wb3ApKSsKICAgIGdlb21fcG9pbnQoc2l6ZT0yKSsKICAgIHRoZW1lX2NsYXNzaWMoKSt5bGFiKCJOZSIpK3hsYWIoIlRpbWUgcGVyaW9kIikrCiAgICBnZW9tX3BhdGgoYWVzKHg9dmFyaWFibGUsIHk9dmFsdWUsIGdyb3VwPXBvcCxjb2xvcj1wb3ApKSsKICAgIHRoZW1lKGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCkpKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2xzKQpnZ3NhdmUoIi4uL091dHB1dC9OZS9OZV9lc3RpbWF0ZXNfb3ZlcnRpbWVfM3BvcHMucG5nIiwgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCBkcGk9MTUwKQpgYGAKCiFbXSguLi9PdXRwdXQvTmUvTmVfZXN0aW1hdGVzX292ZXJ0aW1lXzNwb3BzLnBuZykKCgoKIyMgVXNlIHRoZSBKb3JkZS1SeW1hbiB0ZW1wb3JhbCBtZXRob2QgZnJvbSBOZUVzdGltYXRvciAyLjEuCgpGcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9waW5za3lsYWIvY29kRXZvbCBjYWxjTmVfQU5HU0QuciAKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShib290KQpzb3VyY2UoIi4uL1JzY3JpcHRzL2NhbGNOZS5SIikKYGBgCgojIyMgMS4gUmVhZCB0aGUgbWFmcyBkYXRhIGZyb20gQU5HU0QgJiB0cmltIHBvc2l0aW9ucyB0byB1bmxpbmtlZCBsb2NpClN0YXJ0aW5nIHdpdGggUFdTIHBvcCAgCmBgYHtyIGV2YWw9RkFMU0V9CiNNQUYgZGF0YQpkYXQ5MTwtZnJlYWQoIi4uL0RhdGEvbmV3X3ZjZi9BRi9QV1M5MS5tYWZzLmd6IikKZGF0OTY8LWZyZWFkKCIuLi9EYXRhL25ld192Y2YvQUYvUFdTOTYubWFmcy5neiIpCmRhdDA3PC1mcmVhZCgiLi4vRGF0YS9uZXdfdmNmL0FGL1BXUzA3Lm1hZnMuZ3oiKQpkYXQxNzwtZnJlYWQoIi4uL0RhdGEvbmV3X3ZjZi9BRi9QV1MxNy5tYWZzLmd6IikKc2V0a2V5KGRhdDkxLCBjaHJvbW8sIHBvc2l0aW9uKQpzZXRrZXkoZGF0OTYsIGNocm9tbywgcG9zaXRpb24pCnNldGtleShkYXQwNywgY2hyb21vLCBwb3NpdGlvbikKc2V0a2V5KGRhdDE3LCBjaHJvbW8sIHBvc2l0aW9uKQoKIyB1bmxpbmtlZCBsb2NpIGZyb20gcGxpbmsKdW5sbms8LWZyZWFkKCcuLi9EYXRhL3BsaW5rL3BydW5lL3BydW5lXzUwLjUuMC41LnBydW5lLmluJykKc2V0bmFtZXModW5sbmssIGMoImNocm9tbyIsInBvc2l0aW9uIikpCgpkYXQ5MTwtbWVyZ2UoZGF0OTEsIHVubG5rKQpkYXQ5NjwtbWVyZ2UoZGF0OTYsIHVubG5rKQpkYXQwNzwtbWVyZ2UoZGF0MDcsIHVubG5rKQpkYXQxNzwtbWVyZ2UoZGF0MTcsIHVubG5rKQoKYGBgCgojIyMgMi4gQ29tYmluZSB0d28gdGltZSBwb2ludHMgKGNhbGN1bGF0ZSDOlEFGKSwgdHJpbSBsb2NpIHdpdGggZnJlcSA+IDAuMSwgYW5kIGVzdGlhbXRlIE5lIAoKYGBge3IgZXZhbD1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KeWVhcnM8LWMoIjkxIiwiOTYiLCIwNyIsIjE3IikKY29tYjwtdChjb21ibih5ZWFycywgMikpCgplc3ROZTwtZGF0YS5mcmFtZShwb3AxPWNvbWJbLDFdLCBwb3AyPWNvbWJbLDJdKQoKI0dlbmVyYXRpb24gdGltZSAoRykgPSAyLjM1IGFuZCAzLjUKeWVhcnM8LWMoMTk5MSwxOTk2LDIwMDYsMjAxNykKeXJfY29tYjwtZGF0YS5mcmFtZSh0KGNvbWJuKHllYXJzLCAyKSkpCnlyczwteXJfY29tYiRYMi15cl9jb21iJFgxCmdlbnMxPC15cnMvMi4zNQpnZW5zMjwteXJzLzMKCmZvciAoaSBpbiAyOiBucm93KGNvbWIpKXsKICAgIGRmMTwtZ2V0KHBhc3RlMCgiZGF0Iixjb21iW2ksMV0pKQogICAgZGYyPC1nZXQocGFzdGUwKCJkYXQiLGNvbWJbaSwyXSkpCiAgICAKICAgIHNldG5hbWVzKGRmMSwgYygia25vd25FTSIsICduSW5kJyksIGMoImZyZXExIiwgJ25JbmQxJykpCiAgICBzZXRuYW1lcyhkZjIsIGMoImtub3duRU0iLCAnbkluZCcpLCBjKCJmcmVxMiIsICduSW5kMicpKQogICAgCiAgICBkZiA8LSBkZjFbZGYyLCAuKGNocm9tbywgcG9zaXRpb24sIGZyZXExLCBmcmVxMiwgbkluZDEsIG5JbmQyKV1bIWlzLm5hKGZyZXExKSAmICFpcy5uYShmcmVxMikgJiBmcmVxMSA+IDAuMSAmIGZyZXEyID4gMC4xLCBdCiAgICBnMT1nZW5zMVtpXQogICAgZzI9Z2VuczJbaV0KICAgIAogICAgZXN0TmUkTmUxW2ldPC1kZlssIGpyTmUyKGZyZXExLCBmcmVxMiwgbkluZDEsIG5JbmQyLCBnMSldIAogICAgZXN0TmUkTmUyW2ldPC1kZlssIGpyTmUyKGZyZXExLCBmcmVxMiwgbkluZDEsIG5JbmQyLCBnMildIAogICAgCiAgICAjIGJsb2NrIGJvb3RzdHJhcHBpbmcgYWNyb3NzIExHcwogICAgdXEuY2ggPC0gZGZbLCBzb3J0KHVuaXF1ZShjaHJvbW8pKV0KCiAgICBib290LnJlMSA8LSBib290KHVxLmNoLCBqck5lMmJsb2NrLCAxMDAwLCBnZW4gPSBnMSwgYWxsZGF0YSA9IGRmKQogICAgYm9vdC5yZTIgPC0gYm9vdCh1cS5jaCwganJOZTJibG9jaywgMTAwMCwgZ2VuID0gZzIsIGFsbGRhdGEgPSBkZikKICAgIAogICAgZXN0TmUkbWVkaWFuMVtpXTwtbWVkaWFuKGJvb3QucmUxJHRbaXMuZmluaXRlKGJvb3QucmUxJHQpXSkgIyBtZWRpYW4gYm9vdHN0cmFwCiAgICBlc3ROZSRtZWRpYW4yW2ldPC1tZWRpYW4oYm9vdC5yZTIkdFtpcy5maW5pdGUoYm9vdC5yZTIkdCldKSAjIG1lZGlhbiBib290c3RyYXAKICAgIAogICAgZXN0TmUkbWVhbjFbaV08LW1lYW4oYm9vdC5yZTEkdFtpcy5maW5pdGUoYm9vdC5yZTEkdCldKQogICAgZXN0TmUkbWVhbjJbaV08LW1lYW4oYm9vdC5yZTIkdFtpcy5maW5pdGUoYm9vdC5yZTIkdCldKQogICAgCiAgICBjaTE8LWJvb3QuY2koYm9vdC5yZTEsIHR5cGUgPSBjKCdwZXJjJykpCiAgICBjaTI8LWJvb3QuY2koYm9vdC5yZTIsIHR5cGUgPSBjKCdwZXJjJykpCiAgICAKICAgICM5NSUgQy5JLgogICAgZXN0TmUkQ0kubG93MVtpXTwtY2kxJHBlcmNlbnRbNF0KICAgIGVzdE5lJENJLnVwMVtpXTwtY2kxJHBlcmNlbnRbNV0KICAgIAogICAgZXN0TmUkQ0kubG93MltpXTwtY2kyJHBlcmNlbnRbNF0KICAgIGVzdE5lJENJLnVwMltpXTwtY2kyJHBlcmNlbnRbNV0KICAgIAogICAgCiAgICAjcmVzZXQgdGhlIGF0dGlidXRlcwogICAgc2V0bmFtZXMoZGYxLCBjKCJmcmVxMSIsICduSW5kMScpLGMoImtub3duRU0iLCAnbkluZCcpKQogICAgc2V0bmFtZXMoZGYyLCBjKCJmcmVxMiIsICduSW5kMicpLGMoImtub3duRU0iLCAnbkluZCcpKQp9Cgp3cml0ZS5jc3YoZXN0TmUsIi4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfUFdTX0czLmNzdiIpCgojZXN0TmU8LXJlYWQuY3N2KCIuLi9PdXRwdXQvTmUvSm9yZGUtUnltYW5fTmUuZXN0aW1hdGVzX1BXU19HLmNzdiIsIHJvdy5uYW1lcyA9IDEpCmVzdE5lJHllYXI8LWFwcGx5KGVzdE5lWyJwb3AyIl0sMSwgZnVuY3Rpb24oeCkge2lmICh4PT0iOTYiKSB4PTE5OTYKICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHg9PSIwNyIpIHg9MjAwNwogICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoeD09IjE3IikgeD0yMDE3fSkKI0c9Mi4zNSAoTmUxKQpnZ3Bsb3QoZXN0TmVbYygxLDQsNiksXSwgYWVzKHg9eWVhciwgeT1OZTEpKSsKICAgIGdlb21fcG9pbnQoc2l6ZT0yLCBjb2xvcj0iYmx1ZSIpKwogICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IENJLmxvdzEsIHltYXggPSBDSS51cDEpLCB3aWR0aCA9IDAuMiwgY29sb3I9ImJsdWUiKSsKICAgIGdlb21fcGF0aChjb2xvcj0iYmx1ZSIpK3lsYWIoIkVzdGlhbXRlZCBOZSIpK3hsYWIoIlllYXIiKSsKICAgIHRoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKCJQV1MiKQpnZ3NhdmUoIi4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfUFdTX0cyLjM1LnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMywgZHBpPTMwMCkKCmdncGxvdChlc3ROZVtjKDEsNCw2KSxdLCBhZXMoeD15ZWFyLCB5PU5lMikpKwogICAgZ2VvbV9wb2ludChzaXplPTIsIGNvbG9yPSJibHVlIikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gQ0kubG93MiwgeW1heCA9IENJLnVwMiksIHdpZHRoID0gMC4yLCBjb2xvcj0iYmx1ZSIpKwogICAgZ2VvbV9wYXRoKGNvbG9yPSJibHVlIikreWxhYigiRXN0aWFtdGVkIE5lIikreGxhYigiWWVhciIpKwogICAgdGhlbWVfY2xhc3NpYygpK2dndGl0bGUoIlBXUyIpCmdnc2F2ZSgiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19QV1NfRzMucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzLCBkcGk9MzAwKQoKCmBgYAoKYGBge3J9CmtuaXRyOjprYWJsZShlc3ROZSkKYGBgCgoKIVtdKC4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXMucG5nKXt3aWR0aD02MCV9CgoqIFRCIHBvcCAgCgpgYGB7ciBldmFsPUZBTFNFfQojTUFGIGRhdGEKZGF0OTE8LWZyZWFkKCIuLi9EYXRhL25ld192Y2YvQUYvVEI5MS5tYWZzLmd6IikKZGF0OTY8LWZyZWFkKCIuLi9EYXRhL25ld192Y2YvQUYvVEI5Ni5tYWZzLmd6IikKZGF0MDY8LWZyZWFkKCIuLi9EYXRhL25ld192Y2YvQUYvVEIwNi5tYWZzLmd6IikKZGF0MTc8LWZyZWFkKCIuLi9EYXRhL25ld192Y2YvQUYvVEIxNy5tYWZzLmd6IikKc2V0a2V5KGRhdDkxLCBjaHJvbW8sIHBvc2l0aW9uKQpzZXRrZXkoZGF0OTYsIGNocm9tbywgcG9zaXRpb24pCnNldGtleShkYXQwNiwgY2hyb21vLCBwb3NpdGlvbikKc2V0a2V5KGRhdDE3LCBjaHJvbW8sIHBvc2l0aW9uKQoKIyB1bmxpbmtlZCBsb2NpIGZyb20gcGxpbmsKdW5sbms8LWZyZWFkKCcuLi9EYXRhL3BsaW5rL3BydW5lL3BydW5lXzUwLjUuMC41LnBydW5lLmluJykKc2V0bmFtZXModW5sbmssIGMoImNocm9tbyIsInBvc2l0aW9uIikpCgpkYXQ5MTwtbWVyZ2UoZGF0OTEsIHVubG5rKQpkYXQ5NjwtbWVyZ2UoZGF0OTYsIHVubG5rKQpkYXQwNjwtbWVyZ2UoZGF0MDYsIHVubG5rKQpkYXQxNzwtbWVyZ2UoZGF0MTcsIHVubG5rKQoKeWVhcnM8LWMoIjkxIiwiOTYiLCIwNiIsIjE3IikKY29tYjwtdChjb21ibih5ZWFycywgMikpCmVzdE5lPC1kYXRhLmZyYW1lKHBvcDE9Y29tYlssMV0sIHBvcDI9Y29tYlssMl0pCgp5ZWFyczwtYygxOTkxLDE5OTYsMjAwNiwyMDE3KQp5cl9jb21iPC1kYXRhLmZyYW1lKHQoY29tYm4oeWVhcnMsIDIpKSkKeXJzPC15cl9jb21iJFgyLXlyX2NvbWIkWDEKI2dlbnMxPC15cnMvMi4zNQpnZW5zPC15cnMvMwoKZm9yIChpIGluIDE6IG5yb3coY29tYikpewogICAgZGYxPC1nZXQocGFzdGUwKCJkYXQiLGNvbWJbaSwxXSkpCiAgICBkZjI8LWdldChwYXN0ZTAoImRhdCIsY29tYltpLDJdKSkKICAgIAogICAgc2V0bmFtZXMoZGYxLCBjKCJrbm93bkVNIiwgJ25JbmQnKSwgYygiZnJlcTEiLCAnbkluZDEnKSkKICAgIHNldG5hbWVzKGRmMiwgYygia25vd25FTSIsICduSW5kJyksIGMoImZyZXEyIiwgJ25JbmQyJykpCiAgICAKICAgIGRmIDwtIGRmMVtkZjIsIC4oY2hyb21vLCBwb3NpdGlvbiwgZnJlcTEsIGZyZXEyLCBuSW5kMSwgbkluZDIpXVshaXMubmEoZnJlcTEpICYgIWlzLm5hKGZyZXEyKSAmIGZyZXExID4gMC4xICYgZnJlcTIgPiAwLjEsIF0KICAgIGc9Z2Vuc1tpXQogICAgCiAgICBlc3ROZSROZVtpXTwtZGZbLCBqck5lMihmcmVxMSwgZnJlcTIsIG5JbmQxLCBuSW5kMiwgZyldIAoKICAgICMgYmxvY2sgYm9vdHN0cmFwcGluZyBhY3Jvc3MgTEdzCiAgICB1cS5jaCA8LSBkZlssIHNvcnQodW5pcXVlKGNocm9tbykpXQoKICAgIGJvb3QucmUgPC0gYm9vdCh1cS5jaCwganJOZTJibG9jaywgMTAwMCwgZ2VuID0gZywgYWxsZGF0YSA9IGRmKQogICAgZXN0TmUkbWVkaWFuW2ldPC1tZWRpYW4oYm9vdC5yZSR0W2lzLmZpbml0ZShib290LnJlJHQpXSkgIyBtZWRpYW4gYm9vdHN0cmFwCiAgICBlc3ROZSRtZWFuW2ldPC1tZWFuKGJvb3QucmUkdFtpcy5maW5pdGUoYm9vdC5yZSR0KV0pCiAgICBjaTwtYm9vdC5jaShib290LnJlLCB0eXBlID0gYygncGVyYycpKQogICAgIzk1JSBDLkkuCiAgICBlc3ROZSRDSS5sb3dbaV08LWNpJHBlcmNlbnRbNF0KICAgIGVzdE5lJENJLnVwW2ldPC1jaSRwZXJjZW50WzVdCiAgICAKICAgICNyZXNldCB0aGUgYXR0aWJ1dGVzCiAgICBzZXRuYW1lcyhkZjEsIGMoImZyZXExIiwgJ25JbmQxJyksYygia25vd25FTSIsICduSW5kJykpCiAgICBzZXRuYW1lcyhkZjIsIGMoImZyZXEyIiwgJ25JbmQyJyksYygia25vd25FTSIsICduSW5kJykpCn0KCndyaXRlLmNzdihlc3ROZSwiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19UQl9HMy5jc3YiKQoKI2VzdE5lPC1yZWFkLmNzdigiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19UQl9HMy5jc3YiLCByb3cubmFtZXMgPSAxKQplc3ROZSR5ZWFyPC1hcHBseShlc3ROZVsicG9wMiJdLDEsIGZ1bmN0aW9uKHgpIHtpZiAoeD09Ijk2IikgeD0xOTk2CiAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh4PT0iMDYiKSB4PTIwMDYKICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHg9PSIxNyIpIHg9MjAxN30pCgpnZ3Bsb3QoZXN0TmVbYygxLDQsNiksXSwgYWVzKHg9eWVhciwgeT1OZSkpKwogICAgZ2VvbV9wb2ludChzaXplPTIsIGNvbG9yPSJibHVlIikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gQ0kubG93LCB5bWF4ID0gQ0kudXApLCB3aWR0aCA9IDAuMiwgY29sb3I9ImJsdWUiKSsKICAgIGdlb21fcGF0aChjb2xvcj0iYmx1ZSIpK3lsYWIoIkVzdGlhbXRlZCBOZSIpK3hsYWIoIlllYXIiKSsKICAgIHRoZW1lX2NsYXNzaWMoKStnZ3RpdGxlKCJUQiIpCmdnc2F2ZSgiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19UQl9HMy5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDMsIGRwaT0zMDApCgpgYGAKIVtdKC4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfVEIucG5nKSAgCgoKKiBTUyBwb3B1bGF0aW9uCmBgYHtyIGV2YWw9RkFMU0V9CiNNQUYgZGF0YQpkYXQ5NjwtZnJlYWQoIi4uL0RhdGEvbmV3X3ZjZi9BRi9TUzk2Lm1hZnMuZ3oiKQpkYXQwNjwtZnJlYWQoIi4uL0RhdGEvbmV3X3ZjZi9BRi9TUzA2Lm1hZnMuZ3oiKQpkYXQxNzwtZnJlYWQoIi4uL0RhdGEvbmV3X3ZjZi9BRi9TUzE3Lm1hZnMuZ3oiKQpzZXRrZXkoZGF0OTYsIGNocm9tbywgcG9zaXRpb24pCnNldGtleShkYXQwNiwgY2hyb21vLCBwb3NpdGlvbikKc2V0a2V5KGRhdDE3LCBjaHJvbW8sIHBvc2l0aW9uKQoKIyB1bmxpbmtlZCBsb2NpIGZyb20gcGxpbmsKdW5sbms8LWZyZWFkKCcuLi9EYXRhL3BsaW5rL3BydW5lL3BydW5lXzUwLjUuMC41LnBydW5lLmluJykKc2V0bmFtZXModW5sbmssIGMoImNocm9tbyIsInBvc2l0aW9uIikpCgpkYXQ5NjwtbWVyZ2UoZGF0OTYsIHVubG5rKQpkYXQwNjwtbWVyZ2UoZGF0MDYsIHVubG5rKQpkYXQxNzwtbWVyZ2UoZGF0MTcsIHVubG5rKQoKeWVhcnM8LWMoIjk2IiwiMDYiLCIxNyIpCmNvbWI8LXQoY29tYm4oeWVhcnMsIDIpKQplc3ROZTwtZGF0YS5mcmFtZShwb3AxPWNvbWJbLDFdLCBwb3AyPWNvbWJbLDJdKQoKeWVhcnM8LWMoMTk5NiwyMDA2LDIwMTcpCnlyX2NvbWI8LWRhdGEuZnJhbWUodChjb21ibih5ZWFycywgMikpKQp5cnM8LXlyX2NvbWIkWDIteXJfY29tYiRYMQpnZW5zPC15cnMvMwoKZm9yIChpIGluIDE6IG5yb3coY29tYikpewogICAgZGYxPC1nZXQocGFzdGUwKCJkYXQiLGNvbWJbaSwxXSkpCiAgICBkZjI8LWdldChwYXN0ZTAoImRhdCIsY29tYltpLDJdKSkKICAgIAogICAgc2V0bmFtZXMoZGYxLCBjKCJrbm93bkVNIiwgJ25JbmQnKSwgYygiZnJlcTEiLCAnbkluZDEnKSkKICAgIHNldG5hbWVzKGRmMiwgYygia25vd25FTSIsICduSW5kJyksIGMoImZyZXEyIiwgJ25JbmQyJykpCiAgICAKICAgIGRmIDwtIGRmMVtkZjIsIC4oY2hyb21vLCBwb3NpdGlvbiwgZnJlcTEsIGZyZXEyLCBuSW5kMSwgbkluZDIpXVshaXMubmEoZnJlcTEpICYgIWlzLm5hKGZyZXEyKSAmIGZyZXExID4gMC4xICYgZnJlcTIgPiAwLjEsIF0KICAgIGc9Z2Vuc1tpXQogICAgCiAgICBlc3ROZSROZVtpXTwtZGZbLCBqck5lMihmcmVxMSwgZnJlcTIsIG5JbmQxLCBuSW5kMiwgZyldIAoKICAgICMgYmxvY2sgYm9vdHN0cmFwcGluZyBhY3Jvc3MgTEdzCiAgICB1cS5jaCA8LSBkZlssIHNvcnQodW5pcXVlKGNocm9tbykpXQoKICAgIGJvb3QucmUgPC0gYm9vdCh1cS5jaCwganJOZTJibG9jaywgMTAwMCwgZ2VuID0gZywgYWxsZGF0YSA9IGRmKQogICAgZXN0TmUkbWVkaWFuW2ldPC1tZWRpYW4oYm9vdC5yZSR0W2lzLmZpbml0ZShib290LnJlJHQpXSkgIyBtZWRpYW4gYm9vdHN0cmFwCiAgICBlc3ROZSRtZWFuW2ldPC1tZWFuKGJvb3QucmUkdFtpcy5maW5pdGUoYm9vdC5yZSR0KV0pCiAgICBjaTwtYm9vdC5jaShib290LnJlLCB0eXBlID0gYygncGVyYycpKQogICAgIzk1JSBDLkkuCiAgICBlc3ROZSRDSS5sb3dbaV08LWNpJHBlcmNlbnRbNF0KICAgIGVzdE5lJENJLnVwW2ldPC1jaSRwZXJjZW50WzVdCiAgICAKICAgICNyZXNldCB0aGUgYXR0aWJ1dGVzCiAgICBzZXRuYW1lcyhkZjEsIGMoImZyZXExIiwgJ25JbmQxJyksYygia25vd25FTSIsICduSW5kJykpCiAgICBzZXRuYW1lcyhkZjIsIGMoImZyZXEyIiwgJ25JbmQyJyksYygia25vd25FTSIsICduSW5kJykpCn0KCndyaXRlLmNzdihlc3ROZSwiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19TU19HMy5jc3YiKQoKI2VzdE5lPC1yZWFkLmNzdigiLi4vT3V0cHV0L05lL0pvcmRlLVJ5bWFuX05lLmVzdGltYXRlc19TU19HMy5jc3YiLCByb3cubmFtZXMgPSAxKQplc3ROZSR5ZWFyPC1hcHBseShlc3ROZVsicG9wMiJdLDEsIGZ1bmN0aW9uKHgpIHtpZiAoeD09Ijk2IikgeD0xOTk2CiAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh4PT0iMDYiKSB4PTIwMDYKICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHg9PSIxNyIpIHg9MjAxN30pCgpnZ3Bsb3QoZXN0TmVbYygxLDMpLF0sIGFlcyh4PXllYXIsIHk9TmUpKSsKICAgIGdlb21fcG9pbnQoc2l6ZT0yLCBjb2xvcj0iYmx1ZSIpKwogICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IENJLmxvdywgeW1heCA9IENJLnVwKSwgd2lkdGggPSAwLjIsIGNvbG9yPSJibHVlIikrCiAgICBnZW9tX3BhdGgoY29sb3I9ImJsdWUiKSt5bGFiKCJFc3RpYW10ZWQgTmUiKSt4bGFiKCJZZWFyIikrCiAgICB0aGVtZV9jbGFzc2ljKCkrZ2d0aXRsZSgiU1MiKQpnZ3NhdmUoIi4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfU1NfRzMucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzLCBkcGk9MzAwKQoKYGBgCiFbXSguLi9PdXRwdXQvTmUvSm9yZGUtUnltYW5fTmUuZXN0aW1hdGVzX1NTX0czLnBuZykKCgoqIFBsb3QgMyBwb3B1bGF0aW9ucyB0b2dldGhlcgpgYGB7ciBldmFsPUZBTFNFfQoKbmU8LWRhdGEuZnJhbWUoKQpwb3BzPC1jKCJQV1MiLCJUQiIsIlNTIikKZm9yIChpIGluIDE6Myl7CiAgICBkZjwtcmVhZC5jc3YocGFzdGUwKCIuLi9PdXRwdXQvTmUvSm9yZGUtUnltYW5fTmUuZXN0aW1hdGVzXyIsIHBvcHNbaV0sIl9HMy5jc3YiKSwgcm93Lm5hbWVzID0gMSkKICAgIGRmJHBvcDwtcG9wc1tpXQogICAgbmU8LXJiaW5kKG5lLCBkZikKfQoKbmUkeWVhcjwtYXBwbHkobmVbInBvcDIiXSwxLCBmdW5jdGlvbih4KSB7aWYgKHg9PSI5NiIpIHg9MTk5NgogICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoeD09NikgeD0yMDA2CiAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh4PT03KSB4PTIwMDcKICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHg9PSIxNyIpIHg9MjAxN30pCm5lMjwtbmVbYygxLDQsNiw3LDEwLDEyLDEzLDE1KSxdCm5lMiRwb3A8LWZhY3RvcihuZTIkcG9wLCBsZXZlbHM9YygiVEIiLCJQV1MiLCJTUyIpKQoKZ2dwbG90KG5lMiwgYWVzKHg9eWVhciwgeT1OZSwgY29sb3I9cG9wKSkrCiAgICBnZW9tX3BvaW50KHNpemU9MikrCiAgICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gQ0kubG93LCB5bWF4ID0gQ0kudXApLCB3aWR0aCA9IDAuMikrCiAgICBnZW9tX3BhdGgoKSt5bGFiKCJFc3RpYW10ZWQgTmUiKSt4bGFiKCJZZWFyIikrCiAgICB0aGVtZV9jbGFzc2ljKCkrCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbHMpCgpnZ3NhdmUoIi4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfM1BvcHVsYXRpb25zX0czLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMywgZHBpPTMwMCkKCmBgYAoKIVtdKC4uL091dHB1dC9OZS9Kb3JkZS1SeW1hbl9OZS5lc3RpbWF0ZXNfM1BvcHVsYXRpb25zX0czLnBuZykKPGJyPgo8YnI+CiMgUGkgbnVsbCBkaXN0cmlidXRpb24KCiMjIDEuIENyZWF0ZSBwZXJzaXRlIHRoZXRhLnBlc3QuZ3ogZmlsZXMgaW4gYW5nc2QKCmBgYHtiYXNofQoKL2hvbWUvamFtY2dpcnIvYXBwcy9hbmdzZC9taXNjL3RoZXRhU3RhdCAgcHJpbnQgL2hvbWUva3Rpc3QvcGgvZGF0YS9hbmdzZC90aGV0YS9QV1M5MV9tYWYwMC50aGV0YXMuaWR4IHwgZ3ppcCA+IC9ob21lL2t0aXN0L3BoL2RhdGEvYW5nc2QvdGhldGEvUFdTOTFfbWFmMDBfdGhldGFzLnBlc3RQRy5negoKIyBSdW4gcHJpbnRUaGV0YS5zaCBhdCBmYXJtCmBgYAoKCiMjIDIuIHJ1biBSIHNjcmlwdHMgYXQgZmFybSB0byBjcmVhdGUgbnVsbCBkaXN0cmlidXRpb24gb2YgZ2Vub21lLXdpZGUgdGhldGFzCgpSdW4gYW5nc2RfdGhldGFfc2l0ZXNodWZmbGVfbnVsbC5zaCBhdCBmYXJtLCB3aGljaCBydW5zIFBpX3NodWZmbGVfcHdzLlIgCiAtIFRha2VzIGxvbmcgdGltZSwgc28gY3JlYXRlIGEgc2NyaXB0IGZvciBlYWNoIHBvcC55ZWFyIGNvbWJpbmF0aW9uIGFuZCBydW4gc2VwYXJhdGVseSAKCk91dHB1dCBmcm9tIHRoZXRhIHNodWZmbGluZyByZXN1bHRzIGFyZSBpbiBEYXRhL3NodWZmbGUvdGhldGEuc2l0ZXNodWZmbGUuNTAwMDAuUFdTOTFfUFdTOTYuY3N2Lmd6CgoKIyMgMy4gQ2FsY3VsYXRlIHAtdmFsdWVzIHVzaW5nIHRoZSByZXN1bHRzIGZyb20gc2h1ZmZsaW5nIGFuZCBwbG90IHRoZSByZXN1bHRzICAKCmBgYHtyIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNmcm9tIGNvZEV2b2wgYW5nc2RfdGhldGFfc2l0ZXNodWZmbGVfbnVsbF9zdGF0cy5SCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBsb2FkIGZ1bmN0aW9ucwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKcmVxdWlyZShkYXRhLnRhYmxlKQpyZXF1aXJlKHBseXIpCnJlcXVpcmUoZ2dwbG90MikKcmVxdWlyZShSQ29sb3JCcmV3ZXIpCgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgcmVhZCBpbiBhbmQgcHJlcCBkYXRhCiMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKeWVhcnM8LWMoIlBXUzkxIiwiUFdTOTYiLCJQV1MwNyIsIlBXUzE3IikKY29tYjwtdChjb21ibih5ZWFycywgMikpCiMgbWF4IHRoZXRhIHBlciBnZW5vbWUgZnJvbSByZXNodWZmbGluZyAoYWxsIHNpdGVzKSBmcm9tIGFuZ3NkX3RoZXRhX3NpdGVzaHVmZmxlX251bGwucgoKY2hybWF4IDwtIGZyZWFkKCcuLi9EYXRhL25ld192Y2YvY2hyX3NpemVzLmJlZCcpCmNocm1heDwtY2hybWF4WywtMl0KY29sbmFtZXMoY2hybWF4KTwtYygiY2hyIiwgImxlbiIpCmNocm1heCRzdGFydDwtYygwLGN1bXN1bShjaHJtYXgkbGVuKVsxOihucm93KGNocm1heCktMSldKQoKY2hybWF4JGVuZDwtY3Vtc3VtKGNocm1heCRsZW4pCmNocm1heCRtaWRkbGU8LShjaHJtYXgkZW5kLWNocm1heCRzdGFydCkvMitjaHJtYXgkc3RhcnQKCiNzZXRrZXkoY2hybWF4LCBjaHIpCgojRnVuY3Rpb25zIHRvIGNhbGN1bGF0ZSBwLXZhbHVlcyBmcm9tIGNvZEV2b2wKY2FsY3BHIDwtIGZ1bmN0aW9uKHRoZXRhY2hhbmdlLCBudWxsKXsgIyBmb3IgaW5jcmVhc2VzIGluIHRoZXRhCiAgcmV0dXJuKChzdW0obnVsbCA+IHRoZXRhY2hhbmdlKSsxKS8obGVuZ3RoKG51bGwpKzEpKSAjIGVxdWF0aW9uIGZyb20gTm9ydGggZXQgYWwuIDIwMDIgQW0gSiBIdW0gR2VuCn0KY2FsY3BMIDwtIGZ1bmN0aW9uKHRoZXRhY2hhbmdlLCBudWxsKXsgIyBmb3IgZGVjcmVhc2VzIGluIHRoZXRhCiAgcmV0dXJuKChzdW0obnVsbCA8IHRoZXRhY2hhbmdlKSsxKS8obGVuZ3RoKG51bGwpKzEpKSAjIGVxdWF0aW9uIGZyb20gTm9ydGggZXQgYWwuIDIwMDIgQW0gSiBIdW0gR2VuCn0KCgpjb2xzIDwtIGJyZXdlci5wYWwoNCwgJ1BhaXJlZCcpW3JlcCgxOjIsMTMpXQpEYXRhbGw8LWRhdGEudGFibGUoKQpmb3IgKHAgaW4gMTogbnJvdyhjb21iKSl7CiAgICAjIG1heCB0aGV0YSBwZXIgZ2Vub21lIGZyb20gcmVzaHVmZmxpbmcgKGFsbCBzaXRlcykgZnJvbSBhbmdzZF90aGV0YV9zaXRlc2h1ZmZsZV9udWxsLnIKICAgIG51bGw8LWZyZWFkKHBhc3RlMCgnLi4vRGF0YS9zaHVmZmxlL3RoZXRhLnNpdGVzaHVmZmxlLjUwMDAwLicsIGNvbWJbcCwxXSwiXyIsY29tYltwLDJdLCcuY3N2Lmd6JykpCiAgICAKICAgICN1cHBlciBhbmQgbG93ZXIgOTUlCiAgICBudWxsWywgLih0V2RfbDk1ID0gcXVhbnRpbGUobWludFdkLCAwLjA1KSwgdFdkX3U5NSA9IHF1YW50aWxlKG1heHRXZCwgcHJvYnMgPSAwLjk1KSwKICAgICAgICAgICAgICAgIHRQZF9sOTUgPSBxdWFudGlsZShtaW50UGQsIDAuMDUpLCB0UGRfdTk1ID0gcXVhbnRpbGUobWF4dFBkLCBwcm9icyA9IDAuOTUpLAogICAgICAgICAgICAgICAgdERkX2w5NSA9IHF1YW50aWxlKG1pbnREZCwgMC4wNSksIHREZF91OTUgPSBxdWFudGlsZShtYXh0RGQsIHByb2JzID0gMC45NSkpXQoKICAgICNhc3NpZ24ocGFzdGUwKCJudWxsLiIsY29tYltwLDFdLCJfIixjb21iW3AsMl0pLCBudWxsKSAgICAKICAgIAogICAgIyBzbGlkaW5nIHdpbmRvd3MgdGhldGEgY2hhbmdlIChHQVRLIHNpdGVzKSBmcm9tIGFuZ3NkX3RoZXRhX3NpdGVzaHVmZmxlX251bGwucgogICAgZGF0PC1mcmVhZChwYXN0ZTAoJy4uL0RhdGEvc2h1ZmZsZS90aGV0YV9jaGFuZ2VfcmVnaW9uXzUwMDAwLicsIGNvbWJbcCwxXSwiXyIsY29tYltwLDJdLCcuY3N2Lmd6JyksIGRyb3AgPSAxKQogICAgZGF0Wyxwb3A6PXBhc3RlMChjb21iW3AsMV0sIl8iLGNvbWJbcCwyXSldCiAgICAKICAgIGRhdDwtbWVyZ2UoZGF0LCBjaHJtYXhbLGMoImNociIsInN0YXJ0IildLCBieS54PSJDaHJvbW8iLCBieS55ID0gImNociIpCiAgICBkYXRbLCBQT1NnZW4gOj0gV2luQ2VudGVyICsgc3RhcnRdCiAgICBkYXRbLHN0YXJ0IDo9IE5VTExdICNyZW1vdmUgc3RhcnQKICAgIAogICAgI2NhbGN1bGF0ZSBwLXZhbHVlcwogICAgIzEuIHRoZXRhVyBsb2NpCiAgICBkYXRbdFdkID4gMCwgdFdkLnAgOj0gY2FsY3BHKHRXZCwgbnVsbCRtYXh0V2QpLCBieSA9IC4oQ2hyb21vLCBXaW5DZW50ZXIpXSAjIHRoZXRhVyAgbG9jaQogICAgZGF0W3RXZCA8PSAwLCB0V2QucCA6PSBjYWxjcEwodFdkLCBudWxsJG1pbnRXZCksIGJ5ID0gLihDaHJvbW8sIFdpbkNlbnRlcildCiAgICAjMi4gdGhldGEgcGkKICAgIGRhdFt0UGQgPiAwLCB0UGQucCA6PSBjYWxjcEcodFBkLCBudWxsJG1heHRQZCksIGJ5ID0gLihDaHJvbW8sIFdpbkNlbnRlcildICMgdGhldGEgcGkKICAgIGRhdFt0UGQgPD0gMCwgdFBkLnAgOj0gY2FsY3BMKHRQZCwgbnVsbCRtaW50UGQpLCBieSA9IC4oQ2hyb21vLCBXaW5DZW50ZXIpXQogICAgCiAgICAjVGFqaW1hJ3MgRAogICAgZGF0W3REZCA+IDAsIHREZC5wIDo9IGNhbGNwRyh0RGQsIG51bGwkbWF4dERkKSwgYnkgPSAuKENocm9tbywgV2luQ2VudGVyKV0gIyB0YWppbWEncyBECiAgICBkYXRbdERkIDw9IDAsIHREZC5wIDo9IGNhbGNwTCh0RGQsIG51bGwkbWludERkKSwgYnkgPSAuKENocm9tbywgV2luQ2VudGVyKV0KCiAgICB3cml0ZS5jc3YoZGF0LCBmaWxlPWd6ZmlsZShwYXN0ZTAoJy4uL091dHB1dC9QaS9TaHVmZmxlL3RoZXRhX3NpdGVzaHVmZmxlXycsIGNvbWJbcCwxXSwiXyIsY29tYltwLDJdLCcuY3N2Lmd6JykpKQogICAgCiAgICBEYXRhbGw8LXJiaW5kKERhdGFsbCwgZGF0KQp9Cgp3cml0ZS5jc3YoRGF0YWxsLCBmaWxlPWd6ZmlsZShwYXN0ZTAoJy4uL091dHB1dC9QaS9TaHVmZmxlL3RoZXRhX3NpdGVzaHVmZmxlX1BXU19zdW1tYXJ5LmNzdi5neicpKSkKICAgCgojIyBQbG90IHRoZSByZXN1bHRzCgojY2hyb21vc29tZSBudW1iZXIgbG9jYXRpb25zCndpbnN6ID0gNWU0IAoKI0NoYW5nZXMgaW4gUGkgYmV0d2VlbiB5ZWFycwpEYXRhbGwkQ2hyb21vPC1mYWN0b3IoRGF0YWxsJENocm9tbywgbGV2ZWxzPWMocGFzdGUwKCJjaHIiLDE6MjYpKSkKRGF0YWxsJHBvcDwtZmFjdG9yKERhdGFsbCRwb3AsIGxldmVscz1jKCJQV1M5MV9QV1M5NiIsIlBXUzkxX1BXUzA3IiwiUFdTOTFfUFdTMTciLCJQV1M5Nl9QV1MwNyIsIlBXUzk2X1BXUzE3IiwiUFdTMDdfUFdTMTciKSkKCmdncGxvdChEYXRhbGwsIGFlcyhQT1NnZW4sIHRQZC93aW5zeiwgY29sb3IgPSBDaHJvbW8pKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMC41LCBhbHBoYSA9IDAuMykgKwogICAgZmFjZXRfd3JhcCh+cG9wLCBuY29sID0gMSkgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbHMsIGd1aWRlPSJub25lIikgKwogICAgeWxhYignQ2hhbmdlIGluIHBpIHBlciBzaXRlJykreGxhYigiQ2hyb21vc29tZSIpKwogICAgZ2d0aXRsZSgiQ2hhbmdlcyBpbiBQaSIpKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1jaHJtYXgkbWlkZGxlLCBsYWJlbHM9MToyNikrCiAgICB0aGVtZV9idygpCmdnc2F2ZShwYXN0ZTAoJy4uL091dHB1dC9QaS9TaHVmZmxlL0NoYW5nZXNfaW5fUGlfUFdTLnBuZycpLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0gOSwgZHBpID0gMzAwKQogICAgCiMgcGxvdCB0aGV0YV9XYXRlcnNvbiBjaGFuZ2UKZ2dwbG90KERhdGFsbCwgYWVzKFBPU2dlbiwgdFdkL3dpbnN6LCBjb2xvciA9IENocm9tbykpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMC41LCBhbHBoYSA9IDAuMykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xzLCBndWlkZT0ibm9uZSIpICsKICAgIGZhY2V0X3dyYXAofnBvcCwgbmNvbCA9IDEpICsKICB5bGFiKCdDaGFuZ2UgaW4gV2F0dGVyc29ucyB0aGV0YSBwZXIgc2l0ZScpK3hsYWIoIkNocm9tb3NvbWUiKSsKICBnZ3RpdGxlKCJDaGFuZ2VzIGluIFBpIikrCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWNocm1heCRtaWRkbGUsIGxhYmVscz0xOjI2KSsKICAgIHRoZW1lX2J3KCkKZ2dzYXZlKCcuLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX3RoZXRhV19QV1MucG5nJywgd2lkdGggPSA3LjUsIGhlaWdodCA9IDksIGRwaSA9IDMwMCkKCiMgcGxvdCBUYWppbWEncyBEIGNoYW5nZQpnZ3Bsb3QoRGF0YWxsLCBhZXMoUE9TZ2VuLCB0RGQsIGNvbG9yID0gQ2hyb21vKSkgKyAKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjMpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xzLGd1aWRlPSJub25lIikgKwogICAgZmFjZXRfd3JhcCh+cG9wLCBuY29sID0gMSkgKwogICAgeWxhYignQ2hhbmdlIGluIFRhamltYXMgRCBwZXIgd2luZG93JykreGxhYigiQ2hyb21vc29tZSIpKwogICAgZ2d0aXRsZSgiQ2hhbmdlcyBpbiBUYWppbWEncyBEIikrCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWNocm1heCRtaWRkbGUsIGxhYmVscz0xOjI2KSsKICAgIHRoZW1lX2J3KCkKZ2dzYXZlKCcuLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1RhamltYXNEX1BXUy5wbmcnLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0gOSwgZHBpID0gMzAwKQoKYGBgCiFbXSguLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1BpX1BXUy5wbmcpCgohW10oLi4vT3V0cHV0L1BpL1NodWZmbGUvQ2hhbmdlc19pbl90aGV0YVdfUFdTLnBuZykKCiFbXSguLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1RhamltYXNEX1BXUy5wbmcpCgpgYGB7ciBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIHBsb3QgcGkgcC12YWx1ZSB2cy4gcG9zaXRpb24gCmNvbHMgPC0gYnJld2VyLnBhbCg0LCAnUGFpcmVkJylbcmVwKDE6MiwxMyldCkRhdGFsbCRDaHJvbW88LWZhY3RvcihEYXRhbGwkQ2hyb21vLCBsZXZlbHM9YyhwYXN0ZTAoImNociIsMToyNikpKQpEYXRhbGwkcG9wPC1mYWN0b3IoRGF0YWxsJHBvcCwgbGV2ZWxzPWMoIlBXUzkxX1BXUzk2IiwiUFdTOTFfUFdTMDciLCJQV1M5MV9QV1MxNyIsIlBXUzk2X1BXUzA3IiwiUFdTOTZfUFdTMTciLCJQV1MwN19QV1MxNyIpKQoKZ2dwbG90KERhdGFsbCwgYWVzKFBPU2dlbiwgLWxvZzEwKHRQZC5wKSpzaWduKHRQZCksIGNvbG9yID0gQ2hyb21vKSkgKyAKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjMpICsKICAgIGZhY2V0X3dyYXAofnBvcCwgbmNvbCA9IDEpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xzLCBndWlkZT0ibm9uZSIpICt4bGFiKCJDaHJvbW9zb21lIikrCiAgICB5bGFiKCJsb2cxMChQLXZhbHVlKSIpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbG9nMTAoMC4wNSksIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2dyZXknKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wNSksIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2dyZXknKSsKICAgIGdndGl0bGUoIlAtdmFsdWVzIGZvciBjaGFuZ2VzIGluIFBpIikrCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWNocm1heCRtaWRkbGUsIGxhYmVscz0xOjI2KSsKICAgIHRoZW1lX2J3KCkKZ2dzYXZlKCcuLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1BpLnNpdGVzaHVmZmxlLnAtdmFsdWVzX1BXUy5wbmcnLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0xMSwgdW5pdHMgPSAnaW4nLCBkcGkgPSAzMDApCgoKIyBwbG90IHRoZXRhVyBwLXZhbHVlIHZzLiBwb3NpdGlvbiAoYWxsIGxvY2kpCmdncGxvdChEYXRhbGwsIGFlcyhQT1NnZW4sIC1sb2cxMCh0V2QucCkqc2lnbih0V2QpLCBjb2xvciA9IENocm9tbykpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuMykgKwogIGZhY2V0X3dyYXAofnBvcCwgbmNvbCA9IDEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29scywgZ3VpZGU9Im5vbmUiKSAreGxhYigiQ2hyb21vc29tZSIpKwogICAgeWxhYigibG9nMTAoUC12YWx1ZSkiKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBsb2cxMCgwLjA1KSwgbGluZXR5cGUgPSAnZGFzaGVkJywgY29sb3IgPSAnZ3JleScpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAtbG9nMTAoMC4wNSksIGxpbmV0eXBlID0gJ2Rhc2hlZCcsIGNvbG9yID0gJ2dyZXknKSsKICAgICAgZ2d0aXRsZSgiUC12YWx1ZXMgZm9yIGNoYW5nZXMgaW4gVGhldGEiKSsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3M9Y2hybWF4JG1pZGRsZSwgbGFiZWxzPTE6MjYpKwogICAgdGhlbWVfYncoKQpnZ3NhdmUoJy4uL091dHB1dC9QaS9TaHVmZmxlL0NoYW5nZXNfaW5fdGhldGFXLnNpdGVzaHVmZmxlLnAtdmFsdWVzX1BXUy5wbmcnLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0xMSwgdW5pdHMgPSAnaW4nLCBkcGkgPSAzMDApCgojcGxvdCBUYWphbWEncyBEIHAtdmFsdWUgdnMuIHBvc2l0aW9uCmdncGxvdChEYXRhbGwsIGFlcyhQT1NnZW4sIC1sb2cxMCh0RGQucCkqc2lnbih0RGQpLCBjb2xvciA9IENocm9tbykpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjIsIGFscGhhID0gMC4zKSArCiAgICBmYWNldF93cmFwKH5wb3AsIG5jb2wgPSAxKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29scywgZ3VpZGU9Im5vbmUiKSAreGxhYigiQ2hyb21vc29tZSIpKwogICAgeWxhYigibG9nMTAoUC12YWx1ZSkiKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICdkYXNoZWQnLCBjb2xvciA9ICdncmV5JykgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLWxvZzEwKDAuMDUpLCBsaW5ldHlwZSA9ICdkYXNoZWQnLCBjb2xvciA9ICdncmV5JykrCiAgICBnZ3RpdGxlKCJQLXZhbHVlcyBmb3IgY2hhbmdlcyBpbiBUYWppbWEncyBEIikrCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWNocm1heCRtaWRkbGUsIGxhYmVscz0xOjI2KSsKICAgIHRoZW1lX2J3KCkKZ2dzYXZlKCcuLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1RhamltYUQuc2l0ZXNodWZmbGUucC12YWx1ZXNfUFdTLnBuZycsIHdpZHRoID0gNy41LCBoZWlnaHQgPTExLCB1bml0cyA9ICdpbicsIGRwaSA9IDMwMCkKCmBgYAoKIVtdKC4uL091dHB1dC9QaS9TaHVmZmxlL0NoYW5nZXNfaW5fUGkuc2l0ZXNodWZmbGUucC12YWx1ZXNfUFdTLnBuZykKCgohW10oLi4vT3V0cHV0L1BpL1NodWZmbGUvQ2hhbmdlc19pbl90aGV0YVcuc2l0ZXNodWZmbGUucC12YWx1ZXNfUFdTLnBuZykKCiFbXSguLi9PdXRwdXQvUGkvU2h1ZmZsZS9DaGFuZ2VzX2luX1RhamltYUQuc2l0ZXNodWZmbGUucC12YWx1ZXNfUFdTLnBuZykKCiMjIDQuIE91dGxpZXIgcmVnaW9ucyAgCgoKYGBge3IgZXZhbD1GQUxTRX0KIyMjIyMjIyMjIyMjIyMjIyMKIyBwcmludCBvdXRsaWVycwojIyMjIyMjIyMjIyMjIyMjIwoKUGlfb3V0bGllcnM8LURhdGFsbFt0UGQucCA8IDAuMDUsXQpUaGV0YV9vdXRsaWVyczwtRGF0YWxsW3RXZC5wIDwgMC4wNSxdClRhamltYURfb3V0bGllcnM8LURhdGFsbFt0RGQucCA8IDAuMDUsXSAjbm8gb3V0bGllcnMKCnBpPC1kYXRhLmZyYW1lKHRhYmxlKFBpX291dGxpZXJzJHBvcCwgUGlfb3V0bGllcnMkQ2hyb21vKSkKdGhlPC1kYXRhLmZyYW1lKHRhYmxlKFRoZXRhX291dGxpZXJzJHBvcCwgVGhldGFfb3V0bGllcnMkQ2hyb21vKSkKRDwtZGF0YS5mcmFtZSh0YWJsZShUYWppbWFEX291dGxpZXJzJHBvcCwgVGFqaW1hRF9vdXRsaWVycyRDaHJvbW8pKQoKI3Bsb3QgUFdTOTEtOTYsIDk2LTA3LCBhbmQgMDctMTcKeXJzPC1jKCJQV1M5MV9QV1M5NiIsIlBXUzk2X1BXUzA3IiwiUFdTMDdfUFdTMTciKQpjb2wzPC1icmV3ZXIucGFsKDQsIlB1UmQiKVsyOjRdCgpwaTI8LXBpW3BpJFZhcjEgJWluJSB5cnMsXQpwaTIkVmFyMTwtZmFjdG9yKHBpMiRWYXIxLCBsZXZlbHM9eXJzKQpnZ3Bsb3QocGkyLCBhZXMoeD1WYXIyLCB5PUZyZXEsIGZpbGw9VmFyMSkpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOCkpKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbDMpKwogICAgdGhlbWVfY2xhc3NpYygpKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgZ2d0aXRsZShleHByZXNzaW9uKHBhc3RlKCJDaGFuZ2VzIGluICIsIHBpKSkpKwogICAgeGxhYignJykreWxhYignTnVtYmVyIG9mIHJlZ2lvbnMgd2l0aCBQPDAuMDUnKQpnZ3NhdmUoIi4uL091dHB1dC9QaS9TaHVmZmxlL1BpX3NpZ25pZmljYW50X3BlckNocm9tX3BlclBvcC5wbmciLCB3aWR0aCA9IDgsIGhlaWdodCA9IDQsIGRwaT0zMDApIAoKdGgyPC10aGVbdGhlJFZhcjEgJWluJSB5cnMsXQp0aDIkVmFyMTwtZmFjdG9yKHRoMiRWYXIxLCBsZXZlbHM9eXJzKQpnZ3Bsb3QodGgyLCBhZXMoeD1WYXIyLCB5PUZyZXEsIGZpbGw9VmFyMSkpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOCkpKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbDMpKwogICAgdGhlbWVfY2xhc3NpYygpKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgZ2d0aXRsZShwYXN0ZTAoIkNoYW5nZXMgaW4gdGhldGEiKSkrCiAgICB4bGFiKCcnKSt5bGFiKCdOdW1iZXIgb2YgcmVnaW9ucyB3aXRoIFA8MC4wNScpCmdnc2F2ZSgiLi4vT3V0cHV0L1BpL1NodWZmbGUvVGhldGFfc2lnbmlmaWNhbnRfcGVyQ2hyb21fcGVyUG9wLnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNCwgZHBpPTMwMCkgCgpEMjwtRFtEJFZhcjEgJWluJSB5cnMsXQpEMiRWYXIxPC1mYWN0b3IoRDIkVmFyMSwgbGV2ZWxzPXlycykKZ2dwbG90KEQyLCBhZXMoeD1WYXIyLCB5PUZyZXEsIGZpbGw9VmFyMSkpKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOCkpKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbDMpKwogICAgdGhlbWVfY2xhc3NpYygpKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpKwogICAgIGdndGl0bGUocGFzdGUwKCJDaGFuZ2VzIGluIFRhamltYSdzIEQiKSkrCiAgICB4bGFiKCcnKSt5bGFiKCdOdW1iZXIgb2YgcmVnaW9ucyB3aXRoIFA+MC4wNScpCmdnc2F2ZSgiLi4vT3V0cHV0L1BpL1NodWZmbGUvUGlfc2lnbmlmaWNhbnRfcGVyQ2hyb21fcGVyUG9wLnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNCwgZHBpPTMwMCkgCgpgYGAKCiFbXSguLi9PdXRwdXQvUGkvU2h1ZmZsZS9QaV9zaWduaWZpY2FudF9wZXJDaHJvbV9wZXJQb3AucG5nKQoKIVtdKC4uL091dHB1dC9QaS9TaHVmZmxlL1RoZXRhX3NpZ25pZmljYW50X3BlckNocm9tX3BlclBvcC5wbmcpCgpgYGB7ciBlY2hvPVRSVUV9CgpzdW08LWRhdGEuZnJhbWUodGFibGUoUGlfb3V0bGllcnMkcG9wKSkKc3VtMjwtZGF0YS5mcmFtZSh0YWJsZShUaGV0YV9vdXRsaWVycyRwb3ApKQojc3VtMzwtZGF0YS5mcmFtZSh0YWJsZShUYWppbWFEX291dGxpZXJzJHBvcCkpIG5vIG91dGxpZXJzCgpzdW08LWNiaW5kKHN1bSwgc3VtMiRGcmVxKQpjb2xuYW1lcyhzdW0pPC1jKCJQb3BzIiwgIlBpIiwgIlRoZXRhIikKa25pdHI6OmthYmxlKHQoc3VtKSkKYGBgCgotIE1vc3QgZGlmZmVyZW5jZXMgZXhpc3QgYmV0d2VlbiAxOTk2IGFuZCAyMDA3Ci0gQ2hyMjUgaGFzIHRoZSBtb3N0IHNpZ25pZmljYW50IHJlZ2lvbnMgZm9yIGNoYW5nZXMgaW4gUGkgYW5kIFRoZXRhCnM=